Assume a legacy class and method structure like below
public class Foo
{
public void Frob(int a, int b)
{
if (a == 1)
{
if (b == 1)
{
// does something
}
else
{
if (b == 2)
{
Bar bar = new Bar();
bar.Blah(a, b);
}
}
}
else
{
// does something
}
}
}
public class Bar
{
public void Blah(int a, int b)
{
if (a == 0)
{
// does something
}
else
{
if (b == 0)
{
// does something
}
else
{
Baz baz = new Baz();
baz.Save(a, b);
}
}
}
}
public class Baz
{
public void Save(int a, int b)
{
// saves data to file, database, whatever
}
}
And then assume management issues a nebulous mandate to perform unit testing for every new thing we do, be it an added feature, modified requirement, or bug fix.
I may be a stickler for literal interpretation, but I think the phrase "unit testing" means something. It does not mean, for example, that given inputs of 1 and 2 that the unit test of Foo.Frob
should succeed only if 1 and 2 are saved to a database. Based on what I've read, I believe it ultimately means based on inputs of 1 and 2, Frob
invoked Bar.Blah
. Whether or not Bar.Blah
did what it is supposed to do is not my immediate concern. If I'm concerned with testing the entire process, I believe there's another term for that, right? Functional testing? Scenario testing? Whatever. Correct me if I'm being too rigid, please!
Sticking with my rigid interpretation for the moment, let's assume I want to try to utilize dependency injection, with one benefit being that I can mock away my classes so that I can, for example, not persist my test data to a database or file or whatever the case may be. In this case, Foo.Frob
needs IBar
, IBar
needs IBaz
, IBaz
may need a database. Where are these dependencies to be injected? Into Foo
? Or does Foo
merely need IBar
, and then Foo
is responsible for creating an instance of IBaz
?
When you get into a nested structure such as this, you can quickly see there could be multiple dependencies necessary. What is the preferred or accepted method of performing such injection?
Let us start with your last question. Where are the dependencies injected: A common approach is to use constructor injection (as described by Fowler). So Foo
is injected with an IBar
in the constructor. The concrete implementation of IBar
, Bar
in turn has an IBaz
injected into its constructor. And finally the IBaz
implementation (Baz
) has an IDatabase
(or whatever) injected. If you use a DI framework such as Castle Project, you would simply ask the DI container to resolve an instance of Foo
for you. It will then use whatever you have configured to determine which implementation of IBar
you are using. If it determines that your implementation of IBar
is Bar
it will then determine which implementation of IBaz
you are using, etc.
What this approach gives you, is that you can test each of the concrete implementations in isolation, and just check that it invokes the (mocked) abstraction correctly.
To comment on your concerns about being too rigid etc, the only thing I can say is that in my opinion you are choosing the right path. That said, management might be in for a surprise when the actual cost of implementing all those tests becomes apparent to them.
Hope this helps.
the kind of test you described in the first part of your post (when you try all the parts together) it is usually defined as integration test. As a good practice in your solution you should have either a unit test project and an integration test project. In order to inject dependecies in your code the first and most important rule is to code using interfaces. Assumed this, let's say your class contains an interface as a member and you want to inject/mock it: you can either expose it as a property or pass the implementation using the class constructor. I prefer to use properties to expose dependencies, this way the constructor don't become too verbose. I suggest you to use NUnit or MBunit as a testing framework and Moq as a mocking framework (more clear in it's outputs than Rhino mocks) Here's the documentation with a some examples on how to mock with Moq http://code.google.com/p/moq/wiki/QuickStart
Hope it helps
I don't think there is one "preferred" method for addressing this, but one of your main concerns seems to be that with dependency injection, when you create Foo
, you need to also create Baz
which might be unnecessary. One simple way around this is for Bar
not to depend directly on IBaz
but on a Lazy<IBaz>
or a Func<IBaz>
, allowing your IoC container to create an instance of Bar
without immediately creating Baz
.
For example:
public interface IBar
{
void Blah(int a, int b);
}
public interface IBaz
{
void Save(int a, int b);
}
public class Foo
{
Func<IBar> getBar;
public Foo(Func<IBar> getBar)
{
this.getBar = getBar;
}
public void Frob(int a, int b)
{
if (a == 1)
{
if (b == 1)
{
// does something
}
else
{
if (b == 2)
{
getBar().Blah(a, b);
}
}
}
else
{
// does something
}
}
}
public class Bar : IBar
{
Func<IBaz> getBaz;
public Bar(Func<IBaz> getBaz)
{
this.getBaz = getBaz;
}
public void Blah(int a, int b)
{
if (a == 0)
{
// does something
}
else
{
if (b == 0)
{
// does something
}
else
{
getBaz().Save(a, b);
}
}
}
}
public class Baz: IBaz
{
public void Save(int a, int b)
{
// saves data to file, database, whatever
}
}
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