Могу ли я проверить порядок вызова метода с синтаксисом AAA в Rhino-Mocks 3.6?
Можно ли проверить следующий пример, если Method1 называется 1st, затем Method2 вызывается после, а затем Method3, используя синтаксис AAA, в Rhino-mocks 3.6?
// Assert
var mock = MockRepository.GenerateMock<ISomeService>();
// Act
myObject.Service = mock;
// How should I change this part to ensure that Rhino Mocks check the call order as well?
mock.AssertWasCalled(m=>m.Method1());
mock.AssertWasCalled(m=>m.Method2());
mock.AssertWasCalled(m=>m.Method3());
Ответы
Ответ 1
Вот один из способов сделать это...
mock.AssertWasCalled(m=>m.Method1(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method2())));
mock.AssertWasCalled(m=>m.Method2(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method3())));
mock.AssertWasCalled(m=>m.Method3());
Ответ 2
Вы можете, но вы действительно не должны. Вы должны сосредоточиться на тестировании внешнего наблюдаемого поведения, а не на реализации.
Порядок вызова метода может измениться, не затрагивая контракт с клиентом API. В этом случае ваш тест завершится неудачно, даже если это не так.
Короче говоря, тестирование тестирования приводит к хрупким испытаниям. Хрупкие тесты приводят к отказу от тестов. Вы не хотите туда идти.
Надеюсь, что это поможет.
Ответ 3
Вот как это сделать.
var mocks = new MockRepository();
var fooMock = mocks.DynamicMock<IFoo>();
using (mocks.Ordered())
{
fooMock.Expect(x => x.Method1());
fooMock.Expect(x => x.Method2());
}
fooMock.Replay();
var bar = new Bar(fooMock);
bar.DoWork();
fooMock.VerifyAllExpectations();
Нашел ответ из этого блога.
Ответ 4
Здесь, как это сделать, создавая утверждения в каждом вызове метода.
// Arrange - Build the necessary assertions into the stubbed method invocations.
var mock = MockRepository.GenerateMock<ISomeService>();
mock.Stub(m => m.Method1()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method2()));
mock.Stub(m => m.Method2()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method3()));
// Act
myObject.Service = mock;
// Assert - Ensure each expected method was called.
mock.AssertWasCalled(m => m.Method1());
mock.AssertWasCalled(m => m.Method2());
mock.AssertWasCalled(m => m.Method3());
Так как это смешивает нормальный шаблон arr-act-assert, запуская утверждения в середине действия, мне нравится включать очень конкретные сообщения об ошибках для этих экземпляров, чтобы легче выявлять тесты.
mock.Stub(m => m.Method1()).WhenCalled(inv =>
mock.AssertWasNotCalled(m => m.Method2(), opt =>
opt.Message("Method2 cannot be called before Method1.")));
Вы также можете добиться аналогичного результата, сохранив результат каждого вызова в переменной во время шага действия, а затем проверив состояния переменных во время шага assert. Это лучше сохраняет разделение шаблона arr-act-assert, но для написания и поддержания более строгих правил написания и обслуживания.
// Arrange - Build the necessary state variables into the stubbed method invocations.
bool wasMethod1Called;
bool wasMethod2Called;
bool wasMethod2CalledBeforeMethod1;
bool wasMethod3CalledBeforeMethod2;
var mock = MockRepository.GenerateMock<ISomeService>();
mock.Stub(m => m.Method1()).WhenCalled(inv =>
{
wasMethod1Called = true;
});
mock.Stub(m => m.Method2()).WhenCalled(inv =>
{
wasMethod2Called = true;
wasMethod2CalledBeforeMethod1 = !wasMethod1Called;
});
mock.Stub(m => m.Method3()).WhenCalled(inv =>
{
wasMethod3CalledBeforeMethod2 = !wasMethod2Called;
});
// Act
myObject.Service = mock;
// Assert - Ensure each expected method was called, and that they were called in the right order.
mock.AssertWasCalled(m => m.Method1());
mock.AssertWasCalled(m => m.Method2());
mock.AssertWasCalled(m => m.Method3());
Assert.That(wasMethod2CalledBeforeMethod1, Is.False, "Method2 cannot be called before Method1.");
Assert.That(wasMethod3CalledBeforeMethod2, Is.False, "Method3 cannot be called before Method2.");
Ответ 5
Синтаксис mocks.Ordered(), указанный @craastad, - это правильный способ сделать это, но я не мог заставить его работать в RhinoMocks 3.5 - вместо этого мне пришлось настроить его, чтобы работать без экземпляра MockRepository, который @Решение craastad, используемое для вызова Ordered():
var fooMock = MockRepository.GenerateMock<IFoo>();
using (fooMock.GetMockRepository().Ordered())
{
fooMock.Expect(x => x.Method1());
fooMock.Expect(x => x.Method2());
}
var bar = new Bar(fooMock);
bar.DoWork();
fooMock.VerifyAllExpectations();
Если вы это сделаете, вам также необязательно вызывать fooMock.Replay().