views:

116

answers:

2

Just trying to implement unit testing into a brownfield type system. Be aware i'm relatively new into the unit testing world. Its going to be a gradual migration of course because there are just so many areas of pain.

The current problem i'm trying to solve is we followed a lot of bad practices from our VB6 days and in the conversion of our app to .Net. We have LOT AN LOTS of shared/static functions which call other shared functions and those call others and so on. Sometimes depedencies are passed in as parameters and sometimes they are just newed up within the calling function. I've already instructed our developers to stop creating shared functions and instead create instance members and only use those instance members off of interfaces but that doesn't alleviate the current situation. So you must recursively pass in each and every dependency at the top layer for each function in your code path and method signatures are turning into a mess.

I'm hoping this is something that IOC will fix. Currently we are using NUnit/Moq and i'm starting to investigate StructureMap. So far i understand that you pretty much tell StructureMap for x interface i want to default to the concrete class y:

ObjectFactory.Initialize(x=>{x.ForRequestType<IInterface>().TheDefaultIsConcreteType<MyClass>()});

Then to runtime:

var mytype = ObjectFactory.GetInstance<IInterface>();

the IOC container will initialize the correct type for you. Not sure yet how to swap a fake in for the concrete type but hopefully thats simple. Again will IOC solve the problems i was talking about above? Is there a specific IOC framework that will do it better than StructureMap or can they all handle this situation. Any help would be much appreciated.

+3  A: 

Pretty much, it's no silver bullet however.

Note the IOC container should be set at your application root. Not ad-hoc. Otherwise you'd be implementing a service locator which is an anti pattern.

Follow construction injection for your production code, let the IOC container resolve your dependencies. For unit tests you simply hard code your dependencies. This will allow you to use mock objects (test doubles). In other words IOC has nothing to do with unit testing.

Finglas
Thanks for the reply Finglas. What exactly does this all look like? Does it eliminate all the dependency parameters in each method call? How do you easily pass in fakes for each dependency when your doing your unit test?
Actually was confused on what an IoC really was. Like you stated above you don't use the IoC for test code only for production code. You still use constructor injection but your only using the IoC so you don't have to sit there and make whoever is using your class pass in every parameter. What helped me understanding IoC is watching a screencast with James Kovacs over at DnrTV which involved him building is own simple IoC container. Very interesting!! Hmm i don't know how much IoC are going to help in this case. The depedency / initialization graph is all over the place.
You won't be able to do it all in one hit, but with a bit of planning you should be able to get ther incrementally. It might mean creating some less than pretty code in the intermediate phases, but don't be disheartened, it can be done :) good luck!
Nicholas Blumhardt
@user - you'll still have parameters for each constructor. The IOC container will mean you will write a fraction of the code for wiring up your dependencies. Tests will be the same as always, manually wiring up the dependencies to allow test doubles to be swapped in and out. Check out some articles on IOC, I use Ninject personally. DI is a more important concept to master, without DI you'll find testing hard.
Finglas
+1  A: 

IoC is excellent at getting rid of static methods and avoiding dependency delegation, because it is easy for each Class to explicitly declare all dependencies.

As for Unit testing there are two camps:

  • Insert Mocks as instances for dependencies in the IOC container, which you do not want to test in a particular case, and let the container resolve as usual. This works particular well if you want to test several classes as an integrated component.
  • Mock all instances that you need to construct a single object of a class to test and insert these manually. This works particularly well if you want to stick to testing each class individually (your unit is a single class)
Christopher Oezbek