New syntax for Rhino Mocks
I'm trying to figure out a bit how the new AAA syntax in Rhino Mocks works. 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();
}
What does it look like using AAA syntax?
source to share
Most likely like this:
[Test]
public void Test()
{
// Arrange
ISth sth= MockRepository.GenerateMock<ISth>();
sth
.Stub(x => x.A())
.Return("sth");
// Act
FunctionBeingTested(sth);
// Assert
}
To benefit from the new AAA syntax, you need to change your mind a bit. I am trying to explain.
There is a significant difference in my proposal: there is no "Wait-Check". So I suggest not waiting for the call, because there is a return value. My guess is that the method cannot pass the test when not called sth.A
because it will not miss the correct return value. This will lead to at least one of the other statements.
This is actually good.
- you can move Stub to TestInitialize, it doesn't hurt when the stubbed method is not called during testing (this is not an expectation). Your tests will get shorter.
- Your test does not know "how" the system under test performs the task, you check the results only. Your tests will become more convenient.
There is another scenario where you really need to check if a method has been called on the layout. Basically if it returns void. For example: an event, transaction, etc. should be fired. 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 no return value, so there is no stub. This is the perfect case. You can of course 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 it Stub
and AssertWasCalled
in the same test and you have the constraints of the padding arguments that you don't want to write twice. Usually avoid Expect
andVerifyAllExpectations
source to share
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 to your 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 this as I suspect it will.
source to share