I am trying to change my unit testing of ArcGIS, and start using mocks (I use rhino).
When I started to get into writing the tests, I noticed I have to start mocking a lot of objects, and stub a lot of methods for even a single test to pass.
For example - my controller first gets a RelationshipClass
(so I need to stub the IWorkspace
and the returned IRelationshipClass
), then also gets an IFeature
(A stub), and finally calls stubRelClass.GetRelatedObjects(stubFeature)
, to return an ISet
of other IFeatures
.
Is it normal to have to stub so many objects and methods just to make it pass? I also feel like I really need to step over the code (yeah - I know I should have written the tests first, I am still trying this one), in order to figure out what to stub out next, and what I should return.
I am also having problem with mocking com classes which implement more than one interface. In the production code I QI them between the interfaces. How can I create a mock that implements both interfaces at runtime?
Depending on your injection chain, yes, sometimes you have to mock a lot of objects. If you're going multiple levels deep though, it may be indicative of a design fault - objects that are relying on data that is three layers down into your API may not be loosely coupled. You should be able to nip the chain in the bud by just returning a fake object of some kind at some point that has the necessary properties that the layer you're testing at needs.
You should also be able to do most of your mocking in a [SetUp]
method and then have each test just change one or two things.
For mocking multiple interfaces, Rhino has the concept of a MultiMock. I believe the syntax you're after is:
var mock =
MockRepository.DynamicMultiMock<MyType>(
typeof(Interface1),
typeof(Interface2),
....);
It might be a sign of high coupling - which in turn implies a need to reduce dependencies (which will improve design and testability). As a rough guideline, an object should have around 4-6 collaborators max. Anything over that would set off my alarms.
How are Mocks meant to be used?
To me it sounds like untestable code, which is a smell :-(
I would recommend reading http://misko.hevery.com/code-reviewers-guide/. The author is coach responsible for teaching google developers in the testing area. In the article he shows how you can write testable and untestable code.
Further recommended reading: Clean Code (Robert C. Martin) - main focus on how to write clean (which corresponds to testable) code. Working effectively with legacy code (Michael Feather) - shows ways to get untested and untestable code under control.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With