Rhino Mocks использует входные параметры функции-заглушки для создания возвращаемого значения - PullRequest
0 голосов
/ 05 марта 2020

У меня есть два интерфейса:

interface ITimeframe
{
    DateTime beginTime {get;}
    DateTime endTime {get;}
}

interface ITimeframeFactory
{
     ITimeframe Create(Datetime beginTime, DateTime endTime);
}

Мой тестовый объект использует ITimeframeFactory для создания нескольких ITimeframes. Чтобы протестировать мой TestObject, я предоставляю имитацию TimeframeFactory. Поскольку мой тестовый объект обрабатывает созданные таймфреймы, имитируемый TimeframeFactory должен создавать фиктивные таймфреймы, которые возвращают правильные значения.

StackOverflow: как заглушить функцию , похоже, подсказывает в направлении: use WhenCalled :

var mockRepository = new MockRepository();
ITimeframeFactory mockedTimeframeFactory = mockRepository.Stub<ITimeFrameFactory>();

// when the mocked TimeframeFactory is asked to Create a timeframe,
// let it return a new mockedTimeFrame that returns the proper values for BeginTime and EndTime
using (mockRepository.Record())
{
    mockedTimeframeFactory.Stub( (factory) => factory.Create(
        Arg<DateTime>.Is.Anything,
        Arg<DateTime.Is.Anything))
        .WhenCalled( (call) =>
        {
            DateTime beginTime = (DateTime)call.Arguments[0];
            DateTime endTime = (DateTime)call.Arguments[1];

            // mock a new ITimeframe;
            // this ITimeframe should return beginTime and endtime:
            ITimeframe createdTimeframe = mockRepository.Stub<ITimeframe>();
            createdTimeframe.Stub((timeframe) => timeframe.BeginTime).Return(beginTime);
            createdTimeframe.Stub((timeframe) => timeframe.EndTime).Return(endTime);
            call.ReturnValue = createdTimeframe;
        });
}

Использование:

using (mockRepository.Playback())
{
    DateTime beginTime = new DateTime(2020, 1, 1);
    DateTime endTime = new DateTime(2019, 2, 2);

    ITimeframe createdTimeframe = mockedFactory.Create(beginTime, endTime);
    Assert.IsNotNull(createdTimeframe);

    DateTime mockedBeginTime = createdTimeframe.BeginTime;
    DateTime mockedEndTime = createdTimeframe.EndTime;

    Assert.AreEqual(beginTime, mockedBeginTime);
    Assert.AreEqual(endTime, mockedEndTime);
}

Во время mockedFactory.Create (...) Я вижу, что WhenCalled обрабатывается. Во время WhenCalled у него есть надлежащие beginTime и endTime.

call.ReturnValue также работает, потому что после вызова Create значение createdTimeframe не равно нулю.

Однако, когда я хочу проверить Свойства созданного таймфрейма Я получаю исключение:

System.InvalidOperationException: 'Предыдущий метод' ITimeframe.get_BeginTime (); ' требуется возвращаемое значение или исключение для выброса. '

Похоже, что заглушка для selectedTimeframe.Stub недействительна?

Как решить эту проблему?

1 Ответ

0 голосов
/ 05 марта 2020

Решение проще, чем я думал: во время воспроизведения, когда создается фиктивный таймфрейм, этот фиктивный таймфрейм все еще находится в состоянии записи.

Все, что мне нужно сделать, это установить его в состояние воспроизведения, вызвав Replay () .

Таким образом, я могу создать несколько разных таймфреймов, как показано в следующем коде.

using (this.mockRepository.Playback())
{
    List<ITimeframe> createdTimeframes = new List<ITimeframe>();
    DateTime beginTime = new DateTime(2020, 1, 1);
    DateTime endTime = new DateTime(2019, 2, 2);


    for (int i = 0; i < 10; ++i)
    {
        Timeframe createdTimeframe = this.mockedFactory.Create(beginTime, endTime);

        // This should be a new Timeframe, not returned before
        Assert.IsNotNull(createdTimeframe);
        Assert.IsFalse(createdTimeframes.Contains(createdTimeframe));
        createdTimeframes.Add(createdTimeframe);

        // before using the stubs of this timeframe set in in playback:
        createdTimeframe.Replay();
        DateTime mockedBeginTime = createdTimeframe.BeginTime;
        DateTime mockedEndTime = createdTimeframe.EndTime;
        Assert.AreEqual(beginTime, mockedBeginTime);
        Assert.AreEqual(endTime, mockedEndTime);

        // change beginTime and endTime to create a new timeframe
        beginTime = beginTime.AddMonths(i);
        endTime = endTime.AddMonths(-i);
    }
}
...