public static doSomething() {
Database.write("Did something")
}
Makes testing hard because Database is hardcoded. public static doSomething() {
Database.write("Did something")
}
Makes testing hard because Database is hardcoded.In short: static methods are easy to test, methods using static methods (whether static or not) are more difficult to test.
My takeaway: the bar for moving functionality into non-static methods (which will still be decently easy to test) is quite low. If you call a static method, be prepared to own all its functionality when testing the calling method. Taken to logical conclusion, public static methods should be quite small.
It can be a useful tool, but it causes all kinds of weirdness which can completely mitigate any advantages. On my current project I had to strip out most of our uses of PowerMock. While the tests pass on my local machine just fine, many of them fail for no good reason on the CI server.
Offtopic: Time for start using Docker? :p
Well that's why I suggested using Docker: To ensure both environments are exactly the same.
You say they are virtual machines, but how do you provision them? I assume you are using puppet/chef/salt/ansible and creating them from scratch, as opposed to uploading whatever image you used in dev, like you would with Docker.
Presumably where the definition of badly designed includes "uses static methods"? That's something that I hold true, and teach to other people as true, but I have started wondering about it. Whenever I ask why it's bad I get told "it makes testing hard". Well, Powermock can make testing it possible - "but powermock is only for badly designed code". What's badly designed code? And so it goes round.
Is it really that conceptually bad? Or is it just that our testing tools are insufficient, or that the language itself did not make provisions for testing all of its features? I've seen a lot of code recently that uses dependency injection purely for testing, and uses builders instead of constructors all over the place, and it feels like a lot of effort and complexity to avoid using PowerMock.
(Of course, Java was designed by people doing the best they could subject to particular constraints, and is now constrained by backwards compatibility. But other languages provide the same kind of features in better ways (or provide syntax that means builders and dependency injection are much less effort, depending on which way you look at it))
Pragmatically, good design is not the only concern; if you're not writing a library with binary-compatibility concerns, then IMO the syntactic overhead of builders is often a cost that outweighs the benefits. But the design costs of statics and constructors in Java are real enough, and there are very direct costs to using PowerMock (tests are harder to maintain and more brittle as they have to specify which classes they're rewriting, and it can conflict with other things that do bytecode manipulation e.g. test coverage tools).
public static doSomething(Database db){
db.write("did something"
}Basically, this concept means that it's static all the way down, from the top layer to the bottom layer.