Rhino Mocks is one of my favourite pieces of open source software. It has, more than any other piece of code, changed the way I code, for the better, I hope.
Many moons ago I first played with it and like the fact it was strongly typed, NMock2 was the mock framework I was using at the time and it is string based, which can lead to havoc when refactoring.
Back in those days RhinoMocks was only Record-Playback and to be honest it never felt natural to me. Due to popular demand the framework was extended to allow for either the record play back or IMO the more natural AAA syntax
Arrange - Act - Assert
Arrange, Act, Assert to me help break up the way I write my test to make it very clear what I am trying to achieve. I even have code snippets that auto populate my test. I type "mstest" and i get
[TestMethod]
public void Can()
{
//Arrange
//Act
//Assert
Assert.Inconclusive("Test not completed");
}
I also feel this allows newcomer to see what is going on more clearly and also helps them write test first.
How?
Well, in my mind the hardest thing to do when starting TDD is knowing what to write! If you have the code stub with comments as above, it gives you a visual guide to nudge you into progress.
I also find it helps if n00bs actually write the ACT part first, not the ARRANGE. Typically this involves writing 2 lines of code
- create the object and
- call the method you want to test
eg:
[TestMethod]
public void CanValidateCustomerFromCustomerAddPresenter()
{
//Arrange
//Act
var presenter = new CustomerPresenter(view,service);
presenter.Validate(customer);
//Assert
Assert.Inconclusive("Test not completed");
}
The fact the above code wont even compile is irrelevant. It shows intent. Now the developer writing the test has a clear direction of what they need to do. Often this way of TDD fleshes out new tests. To me this (incomplete and fictitious) test straight away is crying out for complimentary tests: eg CanNotValidateCustomerFromCustomerAddPresenterWithNullCustomer etc etc
The fact that I have not even defined what a customer is, means my mind is still open to possibilities.
On top of the benefits of writing the ACT first, I think AAA syntax makes the test more readable in terms of maintaining code bases, as it has the top down procedural look that coders are used to (even OO has top down).
[TestMethod]
public void CanValidateCustomerFromCustomerAddPresenter()
{
//Arrange - Set up mocks (put in your TestInitialize)
var view = MockRepository.GenerateMock<IView>();
var service = MockRepository.GenerateMock<IService>();
//Arrange - Set up your parameters & return objects
var customer = TestFactory.CreateVaildCustomer();
//Arrange - Set up your expectations on your mocks
view.Expect(v=>v.ShowValidation(customer));
service.Expect(s=>s.Validate(customer)).Return(ValidationFactory.Success);
//Act
var presenter = new CustomerPresenter(view,service);
presenter.Validate(customer);
//Assert
view.VerifyAllExpectations();
service.VerifyAllExpectations();
}
Now I have not run this thru a compiler I just threw this down, but to me this is pretty readable. I used Record-playback only for a few months and found it a little confusing, perhaps my pitiful little brain was maxing out on simple syntax, but hey.
If you are not using AAA try it out, it works great with the C# lambda expressions too (as above) which, to me, means you have incredibly readable tests.
*please ignore the fact the test is odd.. I am trying to show readability as opposed to how to write a crap object ;)
**is it incredibly obvious that i am writing MVP triplets ? ;)
3 comments:
One of the things I've found myself doing a lot less with Rhino Mocks 3.5 is setting expectations. Most of the tests I've been writing recently have no expectations at all and even when they do I rarely have more than one mocked class.
In many cases expectations are simply not necessary. If an instance can only be obtained from a dependency and you validate that you have the expected behaviour or value (from the return value or as an expected parameter) then you have eliminated the need to expect that the dependency is invoked.
I also find that using stubs makes the tests a lot less fragile.
Yeah a mock is saying i expect this to be called.. if it doesnt then fail. Thing i want to mock would be commands basically things ie email service desk on failure or show x on the view. Queries can be stubs.
In saying that, dynamic mocks as seen in RM3.5, make tests a lot more flexible anyway; compared to strict mocks, which i dont think anyone really uses anymore
from :
http://rhysc.blogspot.com/2008/09/tdd-fail-fast.html
This is where lots of people go pear shaped. People tend to "Over Mock". If it is not critical that a dependencies method is called then it is not a mock expectation, it is probably just a stub.
I still struggle along with TDD. I know the AAA style is better but I have been coding the Record-Playback instead through lack of knowledge. The Rec-Play style always felt weird to me. Thanks for posting this as it should clean up my test and make them quite a lot more readable.
W.r.t the code, I dont think it will compile as you use var incorrectly (i think)
var view = MockRepository.GenerateMock();
should be
IView view = MockRepository.GenerateMock();
so that the type can be inferred.
I might follow you up with some "rookie" posts on testing. Show some of my code and see if I can get smarter people like you, Col, Seb and Grae to poke fun at it.
Post a Comment