I am implementing a model in Java which requires iterating over a collection and going through a number of identification stages, it involves for loops, while loops etc. It is the sort of thing I want to test at a fine-grained level so that I have confidence it has been implemented properly.
I have used it as an opportunity to start unit testing, as it is something I recognise as being beneficial to my code. I have since been reading a forest of books to get up to speed with JUnit and unit testing.
Basically my question comes down to two conflicting pieces of advice I have received:
1) Statics are evil. Do not touch statics. Do not test privates either, you probably want a class there instead.
2) Use factories for creation to allow dependency injection using parameters - potentially allowing use of mocks and stubs for isolation.
In my example I am looking to perform an operation along the lines of:
double height = 223.42; // this was set iterating over a collection of doubles
//blah
HeightBounds b = HeightBounds.getHeightBounds(height);
//more blah
I have done this in order to avoid building up what would become a very long and complicated block of code, which I can only test in its entirety. This way I have public accessible objects that I can test to ensure the system components all perform correctly.
Common sense says to me there is nothing wrong with static factories, and that they are easily tested, but am I missing something blindingly obvious given I am learning test-driven design?
Thank you
The static factory class introduces coupling between your class and the HeightBounds
class. this might make your class difficult to test, if for example HeightBounds
goes off and looks in DB for information, or reads from a web service etc etc.
If you instead injected an IHeightBounds
implementation into your class then you could mock that out so you could test what happens when the dependencies of you class do certain things.
For example what if HeightBounds
throws an exception? or returns null? Or you want to test when a particular HeightBound
is returned? With an interface it is easy to mock this behaviour, with a static factory it is more difficult as you have manufacture the data to create the desired results in the class.
You could still only have a single implementation of HeightBounds
and would be able to test that in isolation, but you would be able to test your method above without even having an real implementation.
I would probably have an IHeightBoundFactory
interface and inject an implementation into the class.
As for testing the privates, generally you don't want to. You want to be testing one of 2 things, either that the results are what you expected or that the interactions are what you expected.
If you have a method called Add
and a method called GetAll
then you might want to test that when you call Add
and then call GetAll
you get back the one you added. you don't care how this is implemented, just that it works. this is testing the results. Generally in this situation you want to create mock objects that return data. This seems to be your situation.
If when you call Add
you expect that what is being added is logged, then you want to test the interactions with the logging dependency, so you inject a mock dependency and verify that the interaction with that class happened when you called Add
. Generally in this situation you want to create mock objects that have expectations set, and you verify that those expectations have been met. It doesn't look this is necessary in the situation you described above.
Statics are evil. Do not touch statics.
"static" here probably means Singletons, i.e. global state. That is indeed difficult to use in unit tests, and can introduce lots of subtle issues, so it is better to avoid it in general. However, static
members (fields, methods or inner classes) in general are not necessarily a problem per se.
Do not test privates either, you probably want a class there instead.
This is true in general, if you feel the need to test a private method, it is a sign that your API is not fine grained enough, and the enclosing class may be trying to do too much. Often you may identify some coherent group of functionality which is better to extract into a separate class. This improves your design and in turn makes unit testing easier.
A problem with static factories is, that you are not able to replace the factories (and sometime the objects created by the factories) by mocks. - That is one reason why IOC Containers are so usefull.
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