A lot of Java applications use System properties to hold their configuration. It’s very convenient especially for webapps, because you can set these properties from the server’s admin console.
Naturally, somewhere in the code, the properties are checked and a decision is made based on them. The question is: how can that code be well unit-tested?
Take the following class:
And its corresponding test class:
Do these tests run fine? Yes. Do they leave the property wrongly initialized?
@After method runs even if a test throws an exception.
So where’s the problem?
The problem occurs when you enable multi-threaded test runs. In that scenario the tests
are run in parallel, not sequentially, which means that
initialize the “color” property before
actsWithoutBlue() finishes execution, or
vice-versa. Also, if other tests (for other classes) happen to work with real
objects instead of mocks, they will be in trouble as well.
I hope it’s clear that no test should set system properties, under any circumstances. Let’s introduce interface Color:
and the real implementation:
Foo class becomes:
It can now be properly tested using
Done. Now the tests don’t have to set any system property and can run in parallel without affecting one another. By the way, I used a “fake” implementation of Color instead of Mockito or other frameworks. I like to do that, if the interfaces are small - then it really makes no sense to bring in all the weight of an entire mocking framework.
Finally, if you’re wondering how to unit test
SystemColor.read(), I can only tell you that
that’s the kind of code due to which coverage is never 100%. And, after all, I think we can safely
System.getProperty(...) (being a part of the jdk) runs ok.
How does your app read system properties?
Use syntax highlighting in your comments, to make them more readable.