In an attempt to make my code friendly for unit testing, it seems wise to utilize depenency injection. This requires that any dependent class must implement an interface with the exact same set of methods.
I also see advice saying that I shouldn't have an interface for every class, but I don't see how I could possibly follow both pieces of advice. If I want unit testing, every single useful class must adhere to an interface.
Proof: Suppose there exists a class that does not implement any interfaces. If I am able to unit test my entire program, then no other code depends on this class. Therefore this class is useless and might as well be deleted.
Is there something I am misunderstanding? Is there a way to unit test without copy/pasting all of my classes into equivalently structured interfaces?
In order to write effective tests, you do need seams in your code (a place that let's you break your dependencies apart) to allow you to control any dependencies in your code. Interfaces are possibly the most obvious way to do this, but you can use other techniques such as wrapping your dependency in a method on your class under test and declaring that method as protected virtual (c#) and overriding the class for your unit tests. There is a great series of videos on YouTube around TDD that deal with design decisions when doing TDD. Search for "is TDD dead".
When unit testing, you usually just want to mock classes that make external calls (be it a database query or hitting an API). Consequently, you need to have an interface for these classes. However, a lot of times you may have random DTOs or utility classes that do small simple things and don't need to be mocked.
Some languages have tools that let you mock classes without writing a corresponding interface; for instance, Python allows patching arbitrary classes in test code, and the Mockito library for Java can generate a mock object from any class.
There is a school of thought that says when writing unit tests, only the "leaves", i.e. classes and methods which don't invoke other classes within the application, should be unit tested in isolation, and classes that are involved in orchestrating the behavior of other classes should be tested at the acceptance or integration level. This style of testing avoids writing unit tests that depend on mocking most of the classes in your application, and so avoids the need to write interfaces. Martin Fowler's article on mocks covers some of the differences between different styles of testing regarding mocks.
Related
I'm new to unit testing and Mockito. I code to interfaces for best practice but, since I use Mockito, when do I actually need to implement those interfaces for unit testing? Would I only need this if I'm looking for default values different than the ones Mockito mocks provide?
Thanks!
You only "need" an implementation of the class under test ("system under test"). Any collaborators -- which may appear as either injected fields in your class under test, or as parameters to the methods you are calling on your class under test -- may be left as mocked interfaces.
However, the less real objects you use, the more complicated your test becomes as you have to re-write all of the expected behavior for those collaborators as "when(...)" statements. In essence, you practically end up writing the application code a whole second time as the "when(...)" statements.
I try to mock only "deep" objects that have a long chain of dependencies required in order to produce the test scenario I am trying to create. Things like entity classes, transfer objects, etc., should rarely be mocked, and hence they should usually be implemented. Other kinds of objects are a gray area.
Ultimately, you will always want to make sure your actual implementation classes are tested, otherwise there is no point to the test.
I have a project I am trying to learn unit testing and TDD practices with. I'm finding that I'm getting to quite confusing cases where I am spending a long time setting up mocks for a utility class that's used practically everywhere.
From what I've read about unit testing, if I am testing MyClass, I should be mocking any other functionality (such as provided by UtilityClass). Is it acceptable (assuming that UtilityClass itself has a comprehensive set of tests) to just use the UtilityClass rather than setting up mocks for all the different test cases?
Edit: One of the things I am making a lot of setup for.
I am modelling a map, with different objects in different locations. One of the common methods on my utility class is GetDistanceBetween. I am testing methods that have effects on things depending on their individual properties, so for example a test that selects all objects within 5 units of a point and an age over 3 will need several tests (gets old objects in range, ignores old objects out of range, ignores young objects in range, works correctly with multiples of each case) and all of those tests need setup of the GetDistanceBetween method. Multiply that out by every method that uses GetDistanceBetween (almost every one) and the different results that the method should return in different circumstances, and it gets to be a lot of setup.
I can see as I develop this further, there may be more utility class calls, large numbers of objects and a lot of setup on those mock utility classes.
The rule is not "mock everything" but "make tests simple". Mocking should be used if
You can't create an instance with reasonable effort (read: you need a single method call but to create the instance, you need a working database, a DB connection, and five other classes).
Creation of the additional classes is expensive.
The additional classes return unstable values (like the current time or primary keys from a database)
TDD isn't really about testing. Its main benefit is to help you design clean, easy-to-use code that other people can understand and change. If its main benefit was to test then you would be able to write tests after your code, rather than before, with much of the same effect.
If you can, I recommend you stop thinking of them as "unit tests". Instead, think of your tests as examples of how you can use your code, together with descriptions of its behaviour which show why your code is valuable.
As part of that behaviour, your class may want to use some collaborating classes. You can mock these out.
If your utility classes are a core part of your class's behaviour, and your class has no value or its behaviour makes no sense without them, then don't mock them out.
Aaron Digulla's answer is pretty good; I'd rephrase each of his answers according to these principles as:
The behaviour of the collaborating class is complex and independent of the behaviour of the class you're interested in.
Creation of the collaborating class is not a valuable aspect of your class and does not need to be part of your class's responsibility.
The collaborating class provides context which changes the behaviour of your class, and therefore plays into the examples of how you can use it and what kind of behaviour you might expect.
Hope that makes sense! If you liked it, take a look at BDD which uses this kind of vocabulary far more than "test".
In theory you should try to mock all dependencies, but in reality it's never possible. E.g. you are not going to mock the basic classes from the standard library. In your case if the utility class just contains some basic helper methods I think I wouldn't bother to mock it.
If it's more complicated than that or connects to some external resources, you have to mock it. You could consider creating a dedicated mock builder class, that would create you a standard mock (with some standard stubs defined etc), so that you can avoid mocking code duplication in all test classes.
No, it is not acceptable because you are no longer testing the class in isolation which is one of the most important aspects of a unit test. You are testing it with its dependency to this utility even if the utility has its own set of tests. To simplify the creation of mock objects you could use a mock framework. Here are some popular choices:
Rhino Mocks
Moq
NSubstitute
Of course if this utility class is private and can only be used within the scope of the class under test then you don't need to mock it.
Yes, it is acceptable. What's important is to have the UtilityClass thoroughly unit tested and to be able to differentiate if a test is failing because of the Class under test or because of the UtilityClass.
Testing a class in isolation means testing it in a controlled environment, in an environment where one control how the objects behave.
Having to create too many objects in a test setup is a sign that the environment is getting too large and thus is not controlled enough. Time has come to revert to mock objects.
All the previous answers are very good and really match with my point of view about static utility classes and mocking.
You have two types of utilities classes, your own classes you write and the third party utility classes.
As the purpose of an utility class is to provide small set of helper methods, your utility classes or a third party utility classes should be very well tested.
First Case: the first condition to use your own utility class (even if static) without mocking, is to provide a set of valid unit tests for this class.
Second Case: if you use a third party utility library, you should have enough confidence to this library. Most of the time, those libraries are well tested and well maintained. You can use it without mocking its methods.
I have written my units tests, and where external resources are needed it is dealt with by using fakes.
All is good so far. Now i' am faced with the other test phases, mainly integration where i want to repeat the unit test methods against real external resources e.g The Database.
So, What are the recommendations for structuring test projects for Unit Vs Integration testing? I understand some people prefer separate assemblies for unit and Integration?
How would one share common test code between the two assemblies? Should i create a thrid assembly which contains all the Abstract Test Classes and let the unit and integration inherit? I am looking for maximum re-usability...
I hear alot of noise about Dependency Injection (StructureMap), How could one utilise such a tool in the given Unit + Integration test setup?
can anyone share some wisdom? Thanks
I don't think you should physically separate the two. A good solution is to put the Microsoft.TeamFoundation.PowerTools.Tasks.CategoryAttribute above your tests to identify regular and integration tests. When running tests (even with MSBuild) you can decide to run only the tests you're interested in.
Alternatively you can put them in seperate namespaces.
For code that will be executed in setup & teardown phases, the base class approach would work well. For integration tests, you can extract the functionality of your unit tests into well-parameterized non-test methods (preferably placed in another namespace) and call these "common" methods from both unit and integration tests. Putting unit tests, integration tests and common methods into separate namespaces would suffice, there would be no need for extra assemblies.
One approach would be to create a separate file with helper methods that would be used across multiple testing contexts, and then include that file in both your unit tests and your functional tests. For the parts that vary, you could use dependency injection - for example, by passing in different factories. In the unit tests, the factory could build a fake object, and in the functional tests it could insert a real object in to your test database.
Whether you split the tests into two projects or keep them in one might depend on the number of classes/tests you have. Too many classes in a single project would make it difficult to dig through. If you do split them out, helper/common methods could be thrown into a third assembly, or you could make them public in the unit test assembly, and let the integration assembly reference that one. Make things only as complex as you have to.
On our project we have both integration and unit tests together but in separate folders. Our project layout is such that we have separate assemblies for the main sections (Domain, Services, etc). Each assembly has a matching test assembly. Test assemblies are allowed to reference other test assemblies.
This means Services.Test can reference Domain.Test which makes sense to us because Services references Domain in the actual code.
In terms of reusable pieces we have
Builders - These provide a fluent interface for creating the most important/complex objects in our domain. These live in the main test folder for our domain. Our domain test assembly is referenced by all other test assemblies.
Mothers - These insert data into the database. They give back an Id for the inserted row which can be used to load the object if required. These live in the main test folder for our services.
Helpers - These are guys that do small things throughout our testing. For instance we prefer to allow access to collections via IEnuermable so we have a CollectionHelper.AssertCountIsEqualTo<_T>(int count, IEnumerable<_T> collection, string message) which wraps the IEnumerable in a List and asserts a count. Our Helpers all live in a common test which every other test references.
As for an IoC container if you can use one on your project they can be a huge help not only in testing (via auto mocking) but also in general development. With the overheard of registering everything with the contain though it might be a bit much for just testing.
After some experimenting this is how you can re-use test methods:
public abstract class TestBase
{
[TestMethod]
public void BaseTestMethod()
{
Assert.IsTrue(true);
}
}
[TestClass]
public class UnitTest : TestBase
{
}
[TestClass]
public class IntegrationTest : TestBase
{
}
The unit and integration test class will pick up the base class test methods and run them as two separate tests.
You should be able to create a parametised constructor on the base class to inject your mocks or resources.
I think this method can olny be used with classed within the same assembly. So it looks like the single assembly approach will have to do for now.
Thanks for the tips ppl!
If the only difference between many of your unit tests and the corresponding integration tests is that the latter use "real" ressources rather than fakes (mocks), one approach is the following:
Make a flag is_unit_test available to your test class from the outside
In the class setup, make fake or real resources available depending on the flag. For instance if you need to use a DB API that is either real (an instance of class DBreal) or fake (an instance of class DBfake), your initialization may look like if is_unit_test then this.dbapi = new DBfake else this.dbapi = new DBreal. (DBreal and DBfake need to conform to the same interface, let's call it DBapi.)
From the point of view of your test methods, step 2 amounts to (manual) Dependency Injection: The method does not know what class actually implements its dependency (the DB API). Rather, the dependency is injected into the method from the outside.
Where your test cases require the DB API, they use this.dbapi
Now you execute one and the same test class with the flag set for unit testing and without the flag set for integration testing. (How to make the flag available depends on your unit testing framework.)
Obviously, the same approach can be used if you need more than one resource in a test class.
Some people will find the explicit if in step 2 ugly. To make it more "elegant", you could employ an Inversion of Control (IoC) container (in Java for instance Spring or PicoContainer) to semi-automate the Dependency Injection instead. The initialization would then look like this.dbapi = myContainer.create(DBapi).
In simple cases, an IoC container will only complicate things, because configuring the container is not trivial, involves learning, opens the possibility of a new class of mistakes, and involves additional files.
In more complex cases however, the container makes things easier, because if the creation of your resources requires still other resources, the container will take care of their initialization as well and complexity would indeed go down. But unless you really get there, I suggest to KISS.
Unless you have an important reason for separate assemblies, they violate KISS. I suggest to wait for that reason first.
(Note that some people may tell you that Dependency Injection is only done at the class level.
I consider this unwarranted dogmatism. Injection simply means that a caller does not know the exact class it is calling, no matter how it obtained the object. It often becomes more useful when applied at the class level, but depending on your test framework this may make things overly complicated in the above case. Note that some test frameworks have their own injection capabilities, though.)
I would like to know what are your practices when you test your classes.
For example, I like to use inheritance, with my fixtures.
Given two classes BaseClass, SubClass, I make two other classes BaseClassFixture and SubClassFixture (SubClassFixture is a sub class of BaseClassFixture). So I'm sure that I don't break code which use SubClass as a BaseClass (And people who extends my class can be sure if they do things right, by creating another sub class of my fixture).
I do fixture inheritance with interfaces too.
For example, when I create a fixture for IList, I check that any Add, increase Count by one.
When I have a concrete class which implements IList I just create a fixture named MyConcreteClassIListFixture.
In that case, the fixture for my interface is abstract and I let my subclass create the instance for my tests.
I think it's a kind of design by contracts (see Bertrand Meyer), because I check invariant before and after any tests.
I do this especially with published interfaces or classes.
And you... what are your practices ??
My most important rule is that each test should be atomic and should run in no particular order.
For unit tests, they should strictly obey seperation of concerns.
For integration tests, I pay extra attention to make sure they follow the most important rule.
Also, tests should follow the DRY rule as much as possible along with the code.
There are couple of important things when writing unit test.
1) Unit Tests should be independent:
Unit Tests must be independent. This means that your unit test should not depend on external things to run. This includes internet connection, external web services etc.
2) Unit Tests should be fast:
Unit Tests should run fast. You can write unit tests in multiple ways. Some of them include the dataaccess even though you don't need to access data to run the test. You can always use mock objects and mock the data access layer.
3) Good naming convention:
Unit Tests should have good naming convention and should read like stories.
Here is one example:
public class when_user_transfer_money_from_source_account_to_destination_account
public void make_sure_error_is_thrown_when_source_account_has_insufficient_funds()
{
}
Here is a good screencast that covers many of the above points:
http://screencastaday.com/ScreenCasts/32_Introduction_to_Mocking.aspx
I have been hearing that with unit testing we can catch most of the bugs in the code and I really believe that this is true. But my question is in large projects where each class is dependent on many other classes how do you go about unit testing the class ? Stubbing out every other class doesn't make much sense because of both complexity and the time required to write the stubs. What is your opinion about it?
Part of the advantage of using tests, is that it forces you to minimize dependencies thereby creating testable code. By minimizing dependencies you will increase maintainability and reusability of your code, both highly desirable traits.
Since you are introducing tests into an existing code-base, you will no doubt encounter many hard-to-test situations which will require refactoring to test properly. This refactoring will increase the testability of your code, decreasing dependencies at the same time.
The reason why its hard to retrofit code with tests is why many advocate following Test-Driven-Development. If you write your tests first and then write the code to pass the tests, your code will by default be much more testable and decoupled.
Use a mocking framework to stub your classes for you. Mocking frameworks (I use Rhino Mocks for C#/.NET) make it pretty easy to stub out your dependencies. Used with dependency injection, your classes can be easily decoupled from other classes and don't take much work to make them so. Note that sometimes it does become easier to "fake" something rather than mock. I do end up faking a few classes, but usually these are pretty easy to write -- they just contain "good" or "bad" data and return it. No logic involved.
I'm not up to speed on the whole unit testing thing, but I would think that each unit should represent some sort of test. A test case should test some procedure. A procedure may not be confined to a single class.
For instance, if your application can be broken down into atomic components, then a test case could exist for each component and for each applicable chain of transitions between components.
In our project developers have the responsibility of writing and maintaining stubs right from the start.
Even though stubs cost time and money, unit testing provides some undeniable advantages (and you agreed to it too). It allows for automation of the testing process, reduces difficulties of discovering errors contained in more complex pieces of the application, and test coverage is often enhanced because attention is given to each unit.
With my experience I have seen that in projects where we had put unit testing at low priority had to suffer at a later stage where single change either break things or needs extra testing.
Unit testing increases the confidence in me as a software developer.
i prefer to unit test features, which may or may not correspond to individual classes. This granularity of unit testing seems to me to be a better trade-off in the work required for testing, the feedback for the customer (since features are what they pay for), and the long-term utility of the unit tests (embody requirements, illustrate how-to cases)
as a consequence, mocking is rarely required, but some tests span multiple classes
But my question is in large projects
where each class is dependent on many
other classes how do you go about unit
testing the class ?
First, you understand that "each class is dependent on many other classes" is a bad thing, right? And that it isn't a function of having a large project but rather of bad design? (This is one of the benefits of TDD, that it tends to discourage such highly coupled code.)
Stubbing out every other class doesn't
make much sense because of both
complexity and the time required to
write the stubs.
Not to mention that it doesn't help the design problem. Worse, the investment in all the stubs can actually be a hinderance to refactoring, if only a psychological one.
A better approach (IMHO) is to start from inside out on the classes, changing the design as you go. Typically I would approach this by doing what I call "internal dependency injetion". This involves leaving the method signatures unchanged but extracting the data needed from the dependencies and then extracting functions that hold the actual logic. A trivial example might be:
public int foo(A a, B b) {
C c = a.getC();
D d = b.getD();
Bar bar = calculateBar(c, d);
return calculateFoo(bar, this.baz);
}
Bar calculateBar(C c, D d) {
...
}
int calculateFoo(Bar bar, Baz baz) {
...
}
Now I can write a test for calculateBar and calculateBaz, but I don't need to worry in setting up internal states (this.baz) and I don't need to worry about creating mock versions of A and B.
After creating tests like this with the existing interfaces then I look for opportunity to push the changes out to the interface, like changing the Foo method to take C and D rather than A and B.
Any of that make sense?
You're right, stubbing all the classes on which the class you're testing depends on is not worth the effort. And you will have to maintain your mock as well, ifever you change the interfaces.
If the classes used by the one you're testing have already been tested, then it's fine to have a test spanning over several classes.
It sometimes simpler to mock an object : when
object is or uses an external resource such as database or network connection, disk
object is a GUI
object is not [yet] available
object behavior is not deterministic
object is expensive to setup
I feel you may need to refactor to reduce the complexity.
I have found that it can be very helpful to refactor classes (ie break them down) so each has a single responsibility (less complex). Then you can unit test this responsibility. you can use mocking frameworks to easily mock and initialize the dependencies. I find FakeItEasy to be very good and easy to use and you can find good examples
Here are the principles that worked well for us for testability but also for robust design in a very big enterprise project:
Make your dependencies explicit by taking them through class constructors.
Instead of taking concrete classes as dependencies, create interfaces that defines the functionality you need and take those interfaces as dependencies from class constructors instead. This also allows you to apply Dependency Injection pattern if needed.
Use one of the existing frameworks like Moq so you do not need to write a full test implementation of your interfaces but on run time you create your Moq objects from inside your unit test.