So I'm wondering about how unit testing works in regards to dealing external dependencies. Here and elsewhere I've become familiar with dependency injection, and how that allows us to test a unit (A) of code. However, I'm confused about how to test other units (B and C) which are now possess the external dependency so they can inject it into the original unit (A).
For example, say some class Foo uses an external dependency...
class Foo
{
private ExternalDependency ed;
public int doSomethingWithExternalDependency() {...}
}
And class Bar makes use off Foo...
class Bar
{
public int doSomethingWithFoo
{
Foo f = new Foo();
int x = f.doSomethingWithExternalDependency();
// Do some more stuff ...
return result;
}
}
Now, I know that I can use dependency injection so that I can test Foo, but then how do I test Bar? I guess, I can, again, use dependency injection, but at some point some unit needs to actually create the external dependency; so how do I test that unit?
The examples you provide do not use Dependency Injection. Instead, Bar should use Constructor Injection to get a Foo instance, but there's no point in injecting a concrete class. Instead, you should extract an interface from Foo (let's call it IFoo) and inject that into Bar:
public class Bar
{
private IFoo f;
public Bar(IFoo f)
{
this.f = f;
}
public int doSomethingWithFoo
{
int x = this.f.doSomethingWithExternalDependency();
// Do some more stuff ...
return result;
}
}
This enables you to always decouple consumers and dependencies.
Yes, there will still be a place where you must compose the entire application's object graph. We call this place the Composition Root. It's a application infrastructure component, so you don't need to unit test it.
In most cases you should consider using a DI Container for that part, and then apply the Register Resolve Release pattern.
Keep in mind the difference between unit testing and integration testing. In the former, the dependency would be mocked whereby it provides expected behavior for the purpose of testing the class which consumes the dependency. In the latter, an actual instance of the dependency is initialized to see if the whole thing works end-to-end.
In order to use Dependency Injection, your classes would have their dependencies injected into them (several ways to do that - constructor injection, property injection) and would not instantiate them themselves, as you do in your examples.
Additionally, one would extract the interface of each dependency to help with testability and use the interface instead of an implementation type as the dependency.
class Foo
{
private IExternalDependency ed;
public int doSomethingWithExternalDependency() {...}
public Foo(IExternalDependency extdep)
{
ed = extdep;
}
}
What most people do is use a mocking framework to mock the dependencies when testing.
You can mock any object that the class under test depends on (including behavior and return values) - pass the mocks to the class as its dependencies.
This allows you to test the class without relying on the behavior of its (implemented) dependencies.
In some cases, you may want to use fakes or stubs instead of a mocking framework. See this article by Martin Fowler about the differences.
As for getting all the dependencies, all the way down - one uses an IoC container. This is a registry of all of the dependencies in your system and understands how to instantiate each and every class with its dependencies.
When you unit test a class, you should mock its dependencies, to test your class in isolation -- this is regardless of dependency injection.
The answer to your question about Bar is: yes, you should inject Foo. Once you go down the DI path, you will use it across your entire stack. If you really need a new Foo for every doSomethingWithFoo call, you might want to inject a FooFactory (which you can then mock for testing purposes), if you want a single Bar to use many Foos.
I'd like to stress out that in case of unit testing you should have two separate sets of tests: one for Foo.doSomethingWithExternalDependency and another one for Bar.doSomethingWithFoo. In the latter set create mock implementaion of Foo and you test just doSomethingWithFoo assuming that doSomethingWithExternalDependency works properly. You test doSomethingWithExternalDependency in a separate test set.
Related
I am a true lover of performance, but I am aware about the importance of execute automated tests too (until better formal verification methods become mainstream).
The drawback is that when you try to design for testability you start to introduce interfaces to represent your dependencies. As you know, interfaces make your invocations dynamic dispatched over that dependency and reduce the optimization opportunities at compile-time.
class MyDependency
{
void someMethod();
}
class MyUnit
{
// Concrete type reference of MyDependency allows
// to bypass the dynamic dispatch
this(MyDependency mayBeAMock)
{
mayBeAMock.someMethod();
}
unittest
{
// Now how can I get a mock of my dependency without to instantiate it.
auto dep = someBlackMagic.getMock();
auto uut = new MyUnit(dep);
}
}
Does exist a better way to unit test classes without take the dynamic dispatch cost at production. If need, I would can to afford that cost for the unit testing execution but not for the production release.
Im am interested in D and C++ solutions.
One technique I use in D very often is to do compile-time policy replacement:
private struct MyUtilImpl ( HTTPClient )
{
void foo ( )
{
HTTPClient.makeRequest("url");
}
}
version (unittest)
alias MyUtil = MyUtilImpl!FakeHTTPClient;
else
alias MyUtil = MyUtilImpl!RealHTTPClient;
It is very similar to classical dependency injection in spirit but instead of mocking I/O utilities and swapping via interfaces, I do the same at compile time using template parameters.
It also has the benefit of not needing to change anything in rest of the program to start passing interface around.
2 ideas.
You could either make MyUnit a template and pass in a class that implements (or mocks) "someMethod"
Or, if your unit tests rebuild the class you are testing, you could define the Mock and the real version of the class in separate files and conditionally include / link to the one you want.
Of course you have to be careful not to make your tested version too different from the non-test version.
In unit testing with help of mock/fake objects, I wonder whether it's more preferable to initialize the mocks in SetUp or in the test method itself, if my test class contains methods that test the same class (and thus, fake object needed should be the same for all test case). Something like this:
class FooTests
{
Mock<IBar> mockBar;
Foo fooUnderTest;
[SetUp]
public void Setup()
{
mockBar = new Mock<IBar>();
fooUnderTest = new fooUnderTest(mockBar.Object);
}
[Test]
public void MyTest()
{
//setup mock methods
mockBar.SetUp( ... )
//test
fooUnderTest.TestSomething()
//assert something here
}
}
It seems that this will prevent us from duplicating code to mockBar and fooUnderTest in each test case, but the downside is that I have to declare class variables mockBar and fooUnderTest (or is this really a downside?), and it will be problematic if I want to have some special setup (for example, if in some testcase I want to overriede some of the virtual methods of Foo). Any suggestion what is the best practice?
If there is some common setup shared by all tests in a suite/fixture (including setting up some expectations on mock collaborators), MOVE to a Setup method. (Ditto for incidental details that are not relevant to the reader within the test)
If one test case wants to extend common setup, add the specific setup inline within test-case itself
If one test case wants a different setup (inspite of significant overlap), MOVE to different test suite and figure out some other mechanism to share setup (e.g. via composition, utility methods, Object Mothers, etc.)
Should I write unit test for all nested methods or if writing one test for caller is enough?
For instance:
void Main()
{
var x = new A().AFoo();
}
public class A
{
public int AFoo()
{
// some logic
var x = new B().BFoo();
// might have some logic
return x;
}
}
public class B
{
public int BFoo()
{
// some logic
return ???;
}
}
Is that sufficient to write unit test for Main() method or I need to write tests for Main, A.AFoo(), B.BFoo() methods? How deep should I go?
Thanks in advance.
A testing purist would say that you need to create unit tests for classes A and B.
Each class should have all methods tested. If a method can do more than one thing (if you have an if statement, for example), then you should have a test for each path. If the tests are getting too complicated, it's probably a good idea to refactor the code to make the tests simpler.
Note as it stands right now, its hard to test A in isolation because it depends on B. If B is simple, as it is right now, it's probably ok. You might want to name your tests for A integration tests because technically they test both A and B together. Another option would be to have the method AFoo accept as a parameter the instance of B on which it operates. That way you could mock an instance of B and have a true unit test.
Unit tests are supposed to work on units, in the case of OOP the units are classes and the methods of the classes. That means that you should write a separate test class for each class under consideration, and at least one testing method for each method provided in the class. What is more, it is important to isolate the classes as much as possible so that a bug in class B does not cause a failure on class A. This is why Inversion of Control (Dependency Injection) is so useful, because if you can inject the instance of class B into the instance of class A, you can change B to be just a Mock object.
One of the reasons we write unit tests is to explain, in code, exactly how the methods of each class are expected to behave under all conditions, including and especially edge cases. It is hard to detail the expected behaviour of class B by writing tests on the main method.
I would recommend reading some material online explaining test driven development and how to mock objects, and perhaps use some of the excellent mocking libraries that exist such as JMock. See this question for more links.
Unit tests should help you to reduce your debugging effort. So when you just write unit tests for AFoo and none for BFoo, and one of your test fails, you probably won't know if the problem is part of class A or class B. Writing tests for BFoo too will help you to isolate the error in smaller amount of time.
I'm writing program arguments parser, just to get better in TDD, and I stuck with the following problem. Say I have my parser defined as follows:
class ArgumentsParser {
public ArgumentsParser(ArgumentsConfiguration configuration) {
this.configuration = configuration;
}
public void parse(String[] programArguments) {
// all the stuff for parsing
}
}
and I imagine to have ArgumentsConfiguration implementation like:
class ArgumentsConfiguration {
private Map<String, Class> map = new HashMap<String, Class>();
public void addArgument(String argName, Class valueClass) {
map.add(argName, valueClass);
}
// get configured arguments methods etc.
}
This is my current stage. For now in test I use:
#Test
public void shouldResultWithOneAvailableArgument() {
ArgumentsConfiguration config = prepareSampleConfiguration();
config.addArgument("mode", Integer.class);
ArgumentsParser parser = new ArgumentsParser(configuration);
parser.parse();
// ....
}
My question is if such way is correct? I mean, is it ok to use real ArgumentsConfiguration in tests? Or should I mock it out? Default (current) implementation is quite simple (just wrapped Map), but I imagine it can be more complicated like fetching configuration from kind of datasource. Then it'd be natural to mock such "expensive" behaviour. But what is preferred way here?
EDIT:
Maybe more clearly: should I mock ArgumentsConfiguration even without writing any implementation (just define its public methods), use mock for testing and deal with real implementation(s) later, or should I use the simplest one in tests, and let them cover this implementation indirectly. But if so, what about testing another Configuration implementation provided later?
Then it'd be natural to mock such "expensive" behaviour.
That's not the point. You're not mocking complex classes.
You're mocking to isolate classes completely.
Complete isolation assures that the tests demonstrate that classes follow their interface and don't have hidden implementation quirks.
Also, complete isolation makes debugging a failed test much, much easier. It's either the test, the class under test or the mocked objects. Ideally, the test and mocks are so simple they don't need any debugging, leaving just the class under test.
The correct answer is that you should mock anything that you're not trying to test directly (e.g.: any dependencies that the object under test has that do not pertain directly to the specific test case).
In this case, because your ArgumentsConfiguration is so simple, I'd recommend using the real implementation until your requirements demand something more complicated. There doesn't seem to be any logic in your ArgumentsConfiguration class, so it's safe to use the real object. If the time comes where the configuration is more complicated, then an approach you should probably take would be not to create a configuration that talks to some data source, but instead generate the ArgumentsConfiguration object from that datasource. Then you could have a test that makes sure it generates the configuration properly from the datasource and you don't need unnecessary abstractions.
I am doing a unit test on a class that uses the unity dependency injection framework.
This returns null:
ServiceLocator.Current.GetInstance();
How can I get it to return a mock object or just the object itself?
You could make use of Poor Man's injection. Create a default constructor which retrieves the dependencies from the service locator, and forward those dependencies to a "real" constructor which takes them as parameters. That takes care of production situations.
Then when testing the class in question, pass in a fake/mock version of the dependencies to the "real" constructor, bypassing the default one altogether.
MSDN has this example that shows how to implement the service locator pattern with Unity. Essentially, you should pass the service locator object as a constructor argument of your class. This enables you to pass a MockUnityResolver, allowing you to take full control in a unit test.
[TestMethod]
public void InitCallsRunOnNewsController()
{
MockUnityResolver container = new MockUnityResolver();
var controller = new MockNewsController();
container.Bag.Add(typeof(INewsController), controller);
var newsModule = new NewsModule(container);
newsModule.Initialize();
Assert.IsTrue(controller.RunCalled);
}
Are you testing your core "DI integration" code? If not, your normal code should never (well, rarely) be interacting with your DI framework.
Normally your dependencies will be injected via constructor injection, and when testing, you can instead supply mock objects as those constructor dependencies. For example:
public class Foo {
public Foo (IBar bar) {
bar.Lift ();
}
}
With the above code, you can simply mock IBar, and pass it to the Foo constructor.
You can always setup a Container+ServiceLocator and actually fulfill the required dependencies, for example, by registering mocks. See code examples #4 for how to setup a container/locator:
http://blogs.msdn.com/b/miah/archive/2009/05/12/servicelocator-and-unity-be-careful.aspx