views:

29

answers:

3

If I have a type with a big-old (lots of params) constructor, is it a valid approach to implement a protected parameterless constructor simply for the purposes of creating a derived "Fake" type to use for stubbing in unit tests?

The alternative is to extract an interface, but this is not always desireable in a codebase you do not have full control over...

+1  A: 

Since you essentially have to treat protected the same as public, the answer would be no from a strictly object-oriented point of view.

You could add a private parameterless constructor though and invoke it through reflection, if that's not too much hassle.

TToni
+1  A: 

Could you not create a class which extends the class you want to test? That lets you use your own constructor without having to create an interface.

Modifying your code or API to facilitate unit testing is generally undesirable (see the "Should I unit test private methods" debate), so actually using a new class rather than modifying your existing one might be the way forward.

Andy
Implementing a derived type only moves the problem of having to stub, or instantiate the arguments for the base ctor though, no?
Ben Aston
My point was aimed more at addressing the difficulty of making changes within a codebase you don't always have control over - moving it out mitigates that somewhat. As you say, hardly a perfect solution.
Andy
OK, fair point. Really appreciate your input...
Ben Aston
+1  A: 

It's not ideal, but it is valid.

To quote a couple of people who know more about this than me, in The Art of Unit Testing, Roy Osherove talks about unit tests being like a user of the code, and as such providing access specifically for them is not necessarily a bad thing.

And in Working Effectively with Legacy Code, Michael Feathers discusses several such techniques, pointing out that making things protected for testing can be better than making them public, although it's not necessarily the best way to do things. (In fact I'd recommend you read that book if you are working with legacy code, as it sounds like you are).

I think it depends what sort of code it is - if it's a public API where people are likely to take protected access to mean it's designed to be overridden, it's probably a bad idea, but on a typical business app where it's pretty obviously not meant to be overridden, I don't think it's a problem. I certainly do it sometimes in this situation.

Grant Crofton
Can a framework like RhinoMocks assist me when dealing with ctors with large numbers of parameters?
Ben Aston
Well, it can help you make some of the parameters to pass in, if they're mockable (which many things are with Rhino). If they're not, one thing you might be able to do is 'extract interface' on some of the parameter types, use the interface instead of the concrete type, and use Rhino to mock those interfaces. But AFAIK, it can't automatically mock them all for you without you telling it to.
Grant Crofton