unit test smell
Asked Answered
I

3

5

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?

Ihram answered 29/6, 2009 at 6:18 Comment(0)
B
3

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), 
              ....);
Bondholder answered 29/6, 2009 at 6:30 Comment(2)
About introducing an object that cuts the deep levels - it will "save" me from mocking some more objects (since this one object will cover for them), but I'd still need to mock about the same amount of methods, right? Or am I getting this wrong?Ihram
The point is not to "save you" from mocking more objects. The point is that the test is trying to tell you that there's a missing concept in there, that's why it's so complicated.Spiculum
J
3

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?

Jawbone answered 29/6, 2009 at 6:42 Comment(0)
F
2

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.

Flatfooted answered 29/6, 2009 at 6:30 Comment(1)
and if you don't mind a brief commercial break... mockobjects.com/bookSpiculum

© 2022 - 2024 — McMap. All rights reserved.