У меня есть тестовый объект, который принимает фабрику, которая создает таймфреймы.
interface ITimeFrame
{
Datetime BeginTime {get;}
Datetime EndTimd {get;}
}
interface ITimeframeFactory
{
ITimeFrame Create(DateTime beginTime, DateTime endTime);
}
class MyClass
{
public MyClass(ITimeframeFactory timeframeFactory) {...}
public void MyAction() {...}
public void SetIntoPrecondition() {...}
}
Если мой тестовый объект находится в определенном предварительном условии, и я вызываю MyAction, я ожидаю, что таймфрейм вызывается с ожидаемыми значениями для начала и времени окончания. Этот вызов выполняется ровно один раз.
Код будет выглядеть примерно так:
myTestObject.SetIntoPrecondition();
myTestObject.MyAction();
При установке моего тестового объекта в предварительное условие, TimeframeFactory несколько раз предлагается создать Timeframe. В этом тесте я не хочу беспокоиться о SetIntoPreCondition.
[Test]
public void MyAction_IfInPrecondition_CreatesTimeFrame_UsingBeginTimeEndTime()
{
MockRepository mockRepository = new MockRepository();
ITimeframeFactory mockedTimeframeFactory = mockRepository.StrictMock<ITimeframeFactory>();
MyClass testObject = new MyClass(mockedTimeframeFactory);
// before starting the test I need to set the testObject into the precondition
// this will create several Timeframes, which need to have proper values, because they will be
// used in MyAction.
using (mockRepository.Record())
{
// expect several requests to create a TimeFrame
// (or stub if you like, does not change my problem)
// while arranging I don't care about the parameters
mockedTimeframeFactory.Expect((factory) => factory.Create(
Arg<DateTime>.Is.Anything,
Arg<DateTime>.Is.Anything))
// when called, use the input parameters to create a mocked timeframe:
.WhenCalled((call) =>
{
DateTime beginTime = (DateTime)call.Arguments[0];
DateTime endTime = (DateTime)call.Arguments[1];
ITimeframe mockedTimeframe = mockRepository.Stub<ITimeframe>();
mockedTimeframe.Stub((timeframe) => timeframe.BeginTime).Return(beginTime);
mockedTimeframe.Stub((timeframe) => timeframe.EndTime).Return(endTime);
call.ReturnValue = mockedTimeframe;
// set the mockedTimeframe from Record into Replay mode:
mockedTimeframe.Replay();
});
}
Хорошо, запись закончена, теперь мы готовы поставить объект в предварительное условие:
using (mockRepository.Playback())
{
testObject.SetIntoPrecondition();
}
В других тестах и с помощью отладчика я убедился, что это создало несколько таймфреймов. В этих тестах я смог получить доступ к свойствам созданных таймфреймов.
Теперь, когда мое устройство выполнено, я хочу проверить, что если я вызову MyAction, то таймфрейм будет запрошен для создания другого таймфрейма. На этот раз я ожидаю определенных параметров. Поэтому вместо Args<DateTime>.Is.Anything
я хочу проверить значения.
В этом вопросе SO: Как очистить предыдущие ожидания Я прочитал, что должен использовать следующее:
mockRepository.BackToRecordAll() // which calls the other BackToRecordAll with options All
mockRepository.Replay();
Готов переопределить мои ожидания:
DateTime expectedBeginTime = ...
Datetime expectedEndTime = ...
using (mockRepository.Record())
{
// expect several requests to create a TimeFrame
// (or stub if you like, does not change my problem)
// while arranging I don't care about the parameters
mockedTimeframeFactory.Expect((factory) => factory.Create(
Arg<DateTime>.Is.Equal(expectedBeginTime),
Arg<DateTime>.Is.Equal(expectedEndTime))
.WhenCalled((call) =>
{
DateTime beginTime = (DateTime)call.Arguments[0];
DateTime endTime = (DateTime)call.Arguments[1];
ITimeframe mockedTimeframe = mockRepository.Stub<ITimeframe>();
mockedTimeframe.Stub((timeframe) => timeframe.BeginTime).Return(beginTime);
mockedTimeframe.Stub((timeframe) => timeframe.EndTime).Return(endTime);
call.ReturnValue = mockedTimeframe;
// set the mockedTimeframe from Record into Replay mode:
mockedTimeframe.Replay();
});
}
Готов действовать и утверждать:
using (mockRepository.Playback())
{
testObject.MyAction();
}
Увы, я получаю исключение:
Система .InvalidOperationException: 'Method' ITimeframeFactory.Create (равно 1-1-2020 0:00:00, равно 12-12-2000 0:00:00); ' для возврата требуется возвращаемое значение или исключение. '
Так внезапно, когда WhenCalled больше не работает.
По сути, вопрос: если вам нужны ожидания (или заглушка ( )) чтобы ваш StrictMock подготовил ваш объект к тесту, а затем вы хотите изменить ожидания для выполнения теста, тогда, очевидно, BackToRecordAll и Replay недостаточно.