views:

280

answers:

2

Hi,

I am struggling a bit to understand how the new AAA syntax works in Rhino Mocks. Most of my tests look like this:

    [Test]
    public void Test()
    {
        //Setup
        ISth sth= mocks.DynamicMock<ISth>();

        //Expectations
        Expect.Call(sth.A()).Return("sth");

        mocks.ReplayAll();
        //Execution
        FunctionBeingTested(sth);
        //...asserts, etc

        //Verification
        mocks.VerifyAll();
    }

How would it look like using AAA syntax?

+1  A: 

example from Ayende`s blog:

[Test]
public void WhenUserForgetPasswordWillSendNotification_UsingExpect()
{
    var userRepository = MockRepository.GenerateStub<IUserRepository>();
    var notificationSender = MockRepository.GenerateMock<INotificationSender>();

    userRepository.Stub(x => x.GetUserById(5)).Return(new User { Id = 5, Name = "ayende" });
    notificationSender.Expect(x => x.Send(null)).Constraints(Text.StartsWith("Changed"));

    new LoginController(userRepository, notificationSender).ForgotMyPassword(5);

    notificationSender.VerifyAllExpectations();
}

Changes in yours test

[Test]
    public void Test()
    {
        //Arrange
        var sth= MockRepository.GenerateMock<ISth>();  
        sth.Expect(x=>sth.A()).Return("sth");

        //Act
        FunctionBeingTested(sth);

        //Assert
        sth.VerifyAllExpectations();
    }

But that's just a long shot. Wrote it as i suspect it to be.

Arnis L.
+3  A: 

Most probably like this:

[Test]
public void Test()
{
    // Arrange
    ISth sth= MockRepository.GenerateMock<ISth>();

    sth
      .Stub(x => x.A())
      .Return("sth");

    // Act
    FunctionBeingTested(sth);

    // Assert
}

To really benefit from the new AAA syntax, you have to change your mind a bit. I try to explain.

There is a major difference in my proposal: there is no "Expect-Verify". So I propose to not expect the call, because there is a return value. I assume that the method can't pass the test when it didn't call sth.A, because it will miss the correct return value. It will fail at least one of the other asserts.

This is actually a good thing.

  • you can move the Stub to TestInitialize, it does not hurt when the stubbed method is not called in a test (it's not an expectation). Your tests will become shorter.
  • Your test does not know "how" the system under test does the job, you only check the results. Your tests will become more maintainable.


There is another scenario, where you actually need to check if a method had been called on the mock. Mainly if it returns void. For instance: an event should have been fired, the transaction committed and so on. Use AssertWasCalled for this:

[Test]
public void Test()
{
    // Arrange
    ISth sth= MockRepository.GenerateMock<ISth>();

    // Act
    FunctionBeingTested(sth);

    // Assert
    sth
      .AssertWasCalled(x => x.A());
}

Note: there is not return value, so there is no Stub. This is an ideal case. Of course, you could have both, Stub and AssertWasCalled.


There is also Expect and VerifyAllExpectations, which actually behaves like the old syntax. I would only use them when you need Stub and AssertWasCalled in the same test, and you have complext argument constraints which you don't want to write twice. Normally, avoid Expect and VerifyAllExpectations

Stefan Steinegger