Могу ли я проверить порядок вызовов методов с синтаксисом AAA в Rhino-Mocks 3.6? - PullRequest
10 голосов
/ 28 декабря 2011

Можно ли проверить в следующем примере, вызван ли метод Method1 первым, затем метод2 после, а затем 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());

Ответы [ 5 ]

19 голосов
/ 28 декабря 2011

Вот один из способов сделать это ...

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());
9 голосов
/ 28 декабря 2011

Можно, но не стоит.Вы должны сосредоточиться на тестировании внешних наблюдаемых поведений, а не реализации.

Порядок вызова метода может измениться, не влияя на контракт с клиентом API.В этом случае ваш тест не пройден, даже если он не должен.

Короче говоря, реализация тестирования приводит к хрупким тестам.Хрупкие испытания приводят к отказу от испытаний.Вы не хотите туда идти.

Надеюсь, это поможет.

5 голосов
/ 30 ноября 2012

Вот как это сделать красиво.

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();

Нашел ответ из этого блога.

1 голос
/ 30 июля 2014

Вот как это сделать, встроив утверждения в каждый вызов метода.

// 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());

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

mock.Stub(m => m.Method1()).WhenCalled(inv =>
    mock.AssertWasNotCalled(m => m.Method2(), opt =>
        opt.Message("Method2 cannot be called before Method1.")));

Вы также можете достичь аналогичного результата, сохранив результат каждого вызова в переменной на этапе действия, а затем проверив состояния переменных на этапе утверждения. Это лучше сохраняет разделение шаблонаrange-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.");
0 голосов
/ 10 июня 2015

Синтаксис 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 ().

...