I try to use TDD as much as I can. When I do, I stowe all comunication with the outside away in wrapper classes. A few minutes ago, I made a wrapper for the static class Directory, so I can test my other code without talking to the actual file system.
But what about unit testing the wrapper itself? Since I use TDD, it nags me that I haven't written tests for it. On the other hand, It is a wrapper and nothing else, so do I really need to?
I tend to do the same and not worry about unit testing wrapper classes, as long as I've satisfied myself that they contain the bare minimum amount of code. If, as in your case, I were calling a number of methods on the Directory class, I'd create an interface containing each of the methods I'd be using to ensure that I'm able to test as much of the behaviour of my system under test as possible.
As long as you are using integration and/or acceptance tests as well, it's fine not to unit test your wrapper classes directly. If you try to test Directory directly it's an integration test anyway. I would ask myself whether I had an automated test at some level that would fail if I were to remove the interaction with the Directory class from my code.
Bear in mind that the reason you're normally forced to write wrapper classes is because the code you're trying to test is not inherently testable and is a dependency that cannot be mocked out. Creating the wrapper class allows that behaviour to be mocked out.
Related
I have to write some unit tests which depends on other unit tests. For an example, there is a function to move files: move_file(). To test that function, first I'm required to create a file using the function save_file() which involves another method in the same class. Calling save_file function involves calling a cpanel UAPI which involves some authentication. So, calling save_file function is essential to create a file. Is it acceptable to write a unittest to move_file() method using save_file() method to create a file?
It sounds like you are calling the cpanel UAPI from your class, so your tests are integration tests, really. Does that make a difference? Of course.
Generally speaking, in order to test something, you have to set up your system in a meaningful way. How to do this depends on what you are testing.
In unit tests, you're testing the subject in isolation. If it depends on something external, like an API, it's best to create an abstraction or a thin wrapper for it. That's something that you can easily mock or fake in your tests.
But even this abstraction or wrapper has to be tested with the real thing at some point. And that's when you can't fake it any more. You can't move a file that does not exist. Given that, it's perfectly acceptable to call another method to bring your test scenario into the right state.
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.
If created an interface which contains signatures for the static methods I would have a way to test the classes that were dependent on those static methods.
But how would I test the concrete wrapper class that implements the interface and wraps those static methods?
Do i just not test the concrete wrapper class?
It seems like wrapping the static methods has just moved the problem elsewhere. I still have some class, wrapper class, that is hard to test.
You're on the right track, but you're not moving the problem somewhere else -- you're isolating it to prevent that problem from leaking throughout your code base and other tests. I would only view this as a problem if you've made the wrong assumptions about the wrapped behavior or neglected to prove those assumptions. Some testing is required, but at varying degrees of difficulty. How far you choose to test those assumptions will be a trade-off you need to make.
For some scenarios, the wrapper can be tested but will require physical dependencies that you can control. For example, a static method that modifies a file will require that you take the time to setup the file system, or a helper class that downloads a file from a web-server. I like to think of these tests as "integration tests" instead of "unit tests" as they act upon their dependencies instead of running in isolation. As these tests may take longer to execute that standard tests, you may want to exclude them and run them less frequently than your faster unit tests.
For other scenarios, you may not be able to write a test without considerable effort. For example, you may have wrapped the logic that shows a dialog in a separate window -- testing this logic in code would be a lot work, but launching the application and verifying that it works may be enough. You'll take a hit on code-coverage but to me this is an acceptable trade-off.
The key challenge is understanding the assumptions of the wrapped behavior -- eg, what type of exception is thrown from a remote server if web-request is malformed or the network connection is lost? If you don't capture these assumptions correctly, those faults will bubble up into other areas of your code.
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 understand the need to test a class that has logic (for instance, one that can calculate discounts), where you can test the actual class.
But I just started writing unit tests for a project that will act as a repository (get objects from a database). I find myself writing a 'fake' repository that implements an ISomethingRepository interface. It uses a Dictionary<Guid, Something> for storage internally. It implements the Add(Something) and GetById(Guid) methods of the interface.
Why am I writing this? Nothing I'm writing will actually be used by the software when it's deployed, right? I don't really see the value of this exercise.
I also got the advice to use a mock object that I can setup in advance to meet certain expectations. That seems even more pointless to me: of course the test will succeed, I have mocked/faked it to succeed! And I'm still not sure the actual software will perform as it should when connecting to the database...
confused...
Can someone point me in the right direction to help me understand this?
Thank you!
You are not testing your mock object but some other class that is interacting with it. So you could for example test that a controller forwards a save method call to your fake repository. There is something wrong if you are "testing your fake objects"
Don't test the mock class. Do test the production class using the mock class.
The whole point of the test support class is to have something that you can predict its behavior. If you need to test the test support class in order to predict its behavior, there is a problem.
In the fake database article you linked in a comment, the author needs to unit test his fake database because it is his product (at least in the context of the article).
Edit: updated terms to be more consistent.
Mock - created by mocking framework
Fake - created manually, might actually function some.
Test Support - Mocks, Fakes, Stubs, and all the rest. Not production.
The purpose of the mock/stub object is not to be tested instead of the unit you're trying to test, it's to allow you to test that unit without needing other classes.
It's basically so that you can test classes one at a time without having to test all the classes they're also dependent on.
You should not be testing the mock class.
What you normally do is: you create mock classes for all the classes that the class you are testing interact with.
Let's say you are testing a class called Bicycle which takes in the constructor objects of classes Wheel, Saddle, HandleBar,etc.
And then within the class Bike you you want to test test its method GetWeight which probably iterates through each part and calls property/method Weight of them and then returns the total.
What you do:
you write a mock class for each part
(Wheel, saddle etc) which simply
implements the Weight bit
then you pass those mock classes to the Bicycle
test the GetWeight method on the Bicycle class
It that way you can focus on testing the GetWeight on the Bicycle class, in a manner that is independent on other classes (say they are not implemented yet, not deterministic etc.)
Who watches the watchers?
It is interesting for example if the mock implementation throws specific Exceptions for the corner cases, so you know that the classes that use or depend the IRepositorySomething can handle the exceptions that are thrown in real life. Some of these exceptions you can't generate easily with a test database.
You do not test the Mock object with a unit test, but you use it to test classes that depend on it.
Instead of writing a fake class by yourself, you can use a tool (like Rhino or Typemock) to mock it. It is much easier than writing all the mocks yourself. And like others said, there's no need to test fake code, which is no code if you use the tool.
I have actually found two uses for the mock classes that we use in repository implementation testing.
The first is to test the services that use an implementation of the "ISomethingRepository" equivalent that you mention. However, our repository implementations are created by a factory. This means that we do write tests against the "ISomethingRepository", but not against the "MockSomethingRepository" directly. By testing against the interface, we can easily assert that the code coverage for our tests cover 100% of the interface. Code reviews provide simple verification that new interface members are tested. Even if the developers are running against the mock that the factory returns, the build server has a different configuration that tests against the concrete implementation that the factory returns within the nightly builds. It provides the best of both worlds, in terms of test coverage and local performance.
The second use is one that I am surprised that no one else has mentioned. My team is responsible for the middle tier. Our web developers are responsible for the front end of the web products. By building out mock repository implementations, there is not the artificial obstacle of waiting for the database to be modeled and implemented prior to the front-end work starting. Views can be written that will be built off of the mock to provide a minimal amount of "real" data to meet the expectations of the web developers, as well. For example, data can be provided to contain minimum and maximum length string data to verify that neither break their implementation, etc.
Since the factories we use are wired as to which "ISomethingRepository" to return, we have local testing configurations, build testing configurations, production configurations, etc. We purposely are trying to make sure that no team on the project has unreasonable wait times because of another team's implementation time. The largest chunk of wait time is still provided by the development team, but we are able to crank out our domain objects, repositories, and services at a faster pace than the front-end development.
Of course, YMMV. ;-)
You write "fake" class called Stub or Mock object because you want to test an implementation in a simple way without testing the real concrete class. The purpose is to simplify the testing by testing only the Interface (or abstract class).
In your example, you are testing something that has a dictionnary. It might be fill up in real by the database or have a lot of logic behind it. In your "fake" object, you can simplify everything by having all data constant. This way you test only the behavior of the interface and not how the concrete object is built.
There is generally no need to run classical unit tests in the Data Access Layer.
Perhaps you can write integrational style unit test for your Data Acess Classes, that is, Integration Test (= integrating your Data Access Layer Code with the DB) using the features of Unit Testing Frameworks.
For example, in a Spring project you can use Spring Testcontext to start your Spring context inside a unit test, and then connect to a real database and test that the queries returns correct results. You need probably an own database for unit tests, or perhaps you can connect them with a developer DB.
Have a look at the following article for a good explanation of this:
https://web.archive.org/web/20110316193229/http://msdn.microsoft.com/en-us/magazine/cc163358.aspx
Basically, if you write a fake object and it turns out to be fairly complex, it is sometimes worth it to unit test the fake to make sure it works as expected.
Since a repository can be complex, writing unit tests for it often makes sense.