HiveHicks
HiveHicks

Reputation: 2334

How to use Rhino.Mocks AssertWasCalled() correctly?

I call _mocks.ReplayAll(), then one or more _mockedObject.AssertWasCalled() and then _mocks.VerifyAll(). But it tells me that "This action is invalid when the mock object is in record state".

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

What is the correct order to call so that these methods work correctly?

Upvotes: 18

Views: 30367

Answers (3)

Wim Coenen
Wim Coenen

Reputation: 66723

You are mixing the old Record/Replay pattern and the new AAA pattern.

The normal way to set up a "not called with these arguments" expectation while in Record mode looks like this:

_taskDataProvider.Expect(
    p => p.GlobalStateUpdate(task.ID, TaskState.Executing)).Repeat.Never();

Or alternatively, you can use a strict mock which simply doesn't allow unexpected calls.

AssertWasCalled and AssertWasNotCalled are intended for AAA where you put your assertions at the end. With the Record/Replay syntax, both behavior and expecations should be set up at the start before the switch to replay mode.

(AssertWasNotCalled might actually work with Record/Replay also, but I never tried it because I don't like to mix elements from both approaches. It needlessly complicates things.)

Upvotes: 12

Maggie
Maggie

Reputation: 1547

Jon Kruger's blog post "How to use rhino mocks documented through tests" has simple examples of everything you can do with rhino mocks methods. He also shows what you can not do which I found very helpful in learning.

As mentioned before, using the Arrange, Act, Assert Syntax with the static constructors is easier to read. The blog post shows examples of both methods.

Here are examples from Jon's sample code:

New syntax:

 [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));
    }

Old style:

    [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"));
    }

Upvotes: 18

HiveHicks
HiveHicks

Reputation: 2334

Seems like I found the solution. It's seems a bit weird, but it works. It turns out that I need to call ReplayAll() twice for some reason...

This works:

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

Upvotes: -1

Related Questions