TypeMock / Rhino.Mocks - Designing for testability
On the project I work on we use a combination of Rhino.Mocks and TypeMock.
I'd used TypeMock a lot in the past and found it to be superb and I have always been skeptical on the advantages of designing for testability when dealing with domain classes. TypeMock also helped me avoid having to look at IOC, simplifying my domain and the related infrastructure code.
However I decided to give Rhino Mocks a shot and I did find it useful, if you are prepared to accept the limitation that it can only do interfaces/virtual methods/delegates.
In general I decided to favor TypeMock and only use Rhino.Mocks where it fitted the design I wanted, for example I use Rhino Mocks when mocking out dependencies to infrastructure.
There's a lot of debate about the use of TypeMock though, some people seem to disagree with it:
http://vadim-net.blogspot.com/2007/04/typemock-too-powerful-to-use.html
http://weblogs.asp.net/rosherove/archive/2007/04/26/choosing-a-mock-object-framework.aspx
http://www.mockobjects.com/2007/03/stop-designing-for-testability.html
There are also a few people who seem to thing it is worth using though:
http://www.paraesthesia.com/blog/comments.php?id=1086_0_1_0_C
http://www.elilopian.com/2007/02/26/object-oriented-testable-designed-you-must-be-out-of-your-mind/
It’s an interesting discussion and I guess your take on it is affected by many factors including the types of systems you work on and where in the code base you’re working.
As an example in our application we have persistence ignorant domain assemblies (Customer/Order) and separate persistence assemblies containing the repositories (CustomerRepository/RepositoryOrder). Nine times out of 10 we can ensure our domain assemblies never need to access repositories by careful use of NHibernate's features, making the domain classes very easy to unit test.
However in some cases the domain objects do need to call out to the repositories, what should we do then? We need to make sure that what we maintain the ability to test the domain simply. We could have looked at IOC but instead I went for a simpler Registry pattern based approach. You pass in a RepositoryFactory to this registry during initializaiton (constructor injection) and the interfaces of the repositories (though not the implementations) are in the domain assembly (separated interface).
This works fine and because the repositories and the factory implement interfaces I can use Rhino Mocks. Superb, so I can create a mock repository factory and pass it to the registry and that factory will create mock repositories.
This is fine and is a good example of designing for testability. However we also have cases where one domain object (A) uses another complex domain object (B). When testing A we want to mock B but we're happy with the design as it is so we don't want to start shoving interfaces onto B or using dependency injection. In those cases I turn to TypeMock.
No comments:
Post a Comment