Rhinomocks - Насмешливый делегат - PullRequest
3 голосов
/ 13 апреля 2011
public interface IServiceInvoker
{  
    R InvokeService<T, R>(Func<T, R> invokeHandler) where T : class;
}

public class MediaController : Controller
{ 
    private IServiceInvoker _serviceInvoker;
    public MediaController(IServiceInvoker serviceInvoker)
    {
        _serviceInvoker = serviceInvoker;
    }

    public JsonResult GetAllMedia()
    {
        var media = _serviceInvoker.InvokeService<IMediaService, List<MediaBase>>(proxy    => proxy.GetAllMediaInJson());

        JsonResult jsonResult = new JsonResult();
        jsonResult.Data = media;
        jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        return jsonResult;

}


[TestClass]
public class MediaControllerTests
{
    [TestMethod]
    public void GetAllMedia()
    {
        JsonResult data;
        var serviceInvoker = MockRepository.GenerateStub<IServiceInvoker>();
        var media = CreateSeveralMedia();
        serviceInvoker.Stub(c => c.InvokeService<IMediaService, List<MediaBase>>(p => p.GetAllMediaInJson())).Return(media);
        data = new MediaController(serviceInvoker).GetAllMedia();
        serviceInvoker.VerifyAllExpectations();
        Assert.IsNotNull(data);
    }

}

Я заглушаю службу и возвращаю коллекцию.Когда я запускаю этот тест, медиа является нулевым.Любая идея, как я могу установить ожидания от этого макета?

Ответы [ 2 ]

2 голосов
/ 13 июля 2011

Только что нашел решение. Вроде бы немного некрасиво, но это первая итерация, только вероятно, скоро появится более элегантная версия. Идея состоит в том, чтобы создать еще одну заглушку и сопоставить Func<> с ней: Я предоставлю код для моего варианта использования:

[Theory]
[InlineData(342, 31129, 3456)]
public void should_call_service_invoker_and_return_result(int number1, int number2, int expected)
{
    var calculator = MockRepository.GenerateStub<ICalculator>();
    calculator.Stub(_ => _.Add(number1, number2)).Return(expected);
    var serviceInvoker = MockRepository.GenerateStub<ServiceInvoker<ICalculator>>();
    serviceInvoker
        .Stub(_ => _.Invoke(Arg<Func<ICalculator, int>>.Matches(d => d(calculator) == calculator.Add(number1, number2))))
        .Return(expected);
    var serviceConsumer = new ServiceConsumer(serviceInvoker);

    var actual = serviceConsumer.GetAddResultFor(number1, number2);

    Assert.Equal(expected, actual);
}

Расширения xUnit + используются в качестве основы тестирования. Пожалуйста, игнорируйте Theory и InlineData - это просто еще один способ избавиться от ненужных настроек теста

Вот код СУТ:

public class ServiceConsumer
{
    private readonly ServiceInvoker<ICalculator> serviceInvoker;

    public ServiceConsumer(ServiceInvoker<ICalculator> serviceInvoker)
    {
        this.serviceInvoker = serviceInvoker;
    }

    public int GetAddResultFor(int number1, int number2)
    {
        return serviceInvoker.Invoke(_ => _.Add(number1, number2));
    }
}

public class ServiceInvoker<T>
{
    public virtual R Invoke<R>(Func<T, R> func)
    {
        throw new NotImplementedException();
    }
}

public interface ICalculator
{
    int Add(int number1, int number2);
}

Надеюсь, это будет полезно. Любые предложения о том, как добавить больше красоты, приветствуются:)

1 голос
/ 15 апреля 2011

Лямбда в вашем модульном тесте компилируется в метод уровня класса (метод внутри вашего модульного теста).Внутри вашего контроллера другая лямбда компилируется в метод уровня класса (внутри контроллера).Заглушка, установленная в вашем модульном тесте, не соответствует заглушке, выполняемой в вашем контроллере, поэтому Rhino Mocks возвращает значение по умолчанию (ноль)Подробнее здесь: http://groups.google.com/group/rhinomocks/browse_frm/thread/a33b165c16fc48ee?tvc=1

...