Я звоню _mocks.ReplayAll()
, затем один или несколько _mockedObject.AssertWasCalled()
и затем _mocks.VerifyAll()
. Но это говорит мне, что "Это действие недопустимо, когда фиктивный объект находится в рекордном состоянии".
[Test]
public void SetStateExecuting_Should_Set_State_To_Pause_And_Not_Change_GlobalState_When_GlobalState_Is_Paused()
{
var task = new Task { ID = 1, TimeZone = -660, GlobalState = TaskState.Paused };
_taskDataProvider.Expect(p => p.StateUpdate(task.ID, task.TimeZone, TaskState.Paused));
_mockRepository.ReplayAll();
_manager.SetStateExecuting(task);
_taskDataProvider.AssertWasNotCalled(p => p.GlobalStateUpdate(task.ID,
TaskState.Executing));
_mockRepository.VerifyAll();
}
Что состоит в том, чтобы назвать правильный порядок так, чтобы эти методы работали правильно?
Вы смешиваете старый шаблон Record/Replay и новый AAA.
Обычный способ установить ожидание "не вызывать с этими аргументами" в режиме Record выглядит так:
_taskDataProvider.Expect(
p => p.GlobalStateUpdate(task.ID, TaskState.Executing)).Repeat.Never();
Или, в качестве альтернативы, вы можете использовать строгий mock, который просто не допускает неожиданных вызовов.
AssertWasCalled
и AssertWasNotCalled
предназначены для AAA, где вы помещаете свои утверждения в конец. В синтаксисе Record/Replay поведение и утверждения должны быть заданы в начале, до переключения в режим воспроизведения.
(AssertWasNotCalled
на самом деле может работать и с Record/Replay, но я никогда не пробовал, потому что не люблю смешивать элементы обоих подходов. Это излишне усложняет ситуацию)
Похоже, я нашел решение. Это кажется немного странным, но работает. Оказывается, мне по какой-то причине нужно дважды вызвать ReplayAll () ...
Это работает:
[Test]
public void SetStateExecuting_Should_Set_State_To_Pause_And_Not_Change_GlobalState_When_GlobalState_Is_Paused()
{
var task = new Task { ID = 1, TimeZone = -660, GlobalState = TaskState.Paused };
_mockRepository.ReplayAll();
_manager.SetStateExecuting(task);
_taskDataProvider.AssertWasCalled(p => p.StateUpdate(task.ID, task.TimeZone, TaskState.Paused));
_taskDataProvider.AssertWasNotCalled(p => p.GlobalStateUpdate(task.ID, TaskState.Executing));
_mockRepository.ReplayAll();
}
В сообщении в блоге Джона Крюгера «Как использовать макеты носорога, задокументированные с помощью тестов» есть простые примеры всего, что вы можете сделать с помощью методов имита носорога. Он также показывает, чего нельзя делать, что мне очень помогло в обучении.
Как упоминалось ранее, использование синтаксиса Arrange, Act, Assert со статическими конструкторами легче для чтения. В сообщении блога показаны примеры обоих методов.
Вот примеры из примера кода Джона:
Новый синтаксис:
[Test]
public void You_can_check_to_see_if_a_method_was_called()
{
var stub = MockRepository.GenerateStub<ISampleClass>();
stub.MethodThatReturnsInteger("foo");
stub.AssertWasCalled(s => s.MethodThatReturnsInteger("foo"));
stub.AssertWasCalled(s => s.MethodThatReturnsInteger(Arg<string>.Is.Anything));
}
Старый стиль:
[Test]
public void Calling_virtual_methods_will_call_the_actual_method()
{
var mockRepository = new MockRepository();
var sampleClass = mockRepository.PartialMock<SampleClass>();
sampleClass.Replay();
sampleClass.VirtualMethod("foo").ShouldEqual(3);
sampleClass.VirtualMethodWasCalled.ShouldBeTrue();
sampleClass.AssertWasCalled(c => c.VirtualMethod("foo"));
}