Question

Mockito does not allow mocking of final methods. Is it considered bad practice to have final methods in your code? And why?

I don't want to change implementation details just to make test code work, but, often times testing frameworks have these rules to encourage better coding practices.

Was it helpful?

Solution

final methods absolutely are not bad practice in general: They convey a specific piece of information about the behavior and semantics of a method—namely, that anyone calling that method will get exactly that implementation. That's exactly the property you're trying to subvert through mocking, because you're overriding the final implementation through a (dynamically-generated) subclass to perform the stubbed behavior instead.

To that end, if you have an implementation you control that you're trying to replace in tests with a stub, it probably shouldn't be final, because you're treating it as a non-final method yourself in your test. Your test is another user of your component, and one you can design for accordingly.

In implementations you don't control, such as third-party libraries, PowerMock is a generally-accepted solution for mocking constructors as well as private, static and final methods, potentially in final classes. PowerMock does come with some hazards, though:

  • There is additional complexity of mocking: PowerMock works through a special classloader that rewrites the classes themselves, rather than through Java's OOP method dispatch, so you have to explicitly list the classes calling the final and static methods you're stubbing so Powermock can replace those calls.
  • There is additional risk in mocking classes you don't control, if you do so: You may be left in a bad position if the API or implementation changes in an incompatible way.
  • By violating the semantics of the final modifier, it may make your code harder to read—you're declaring the method to have one well-defined predictable behavior and then working around your own declaration.

In terms of "best practices", the real best practice is the OOP tenet jgitter alludes to above: "Program to interfaces, not implementations." By relying on explicit interfaces:

That said, the ease with which Mockito stubs concrete classes makes it a tempting option, but be aware that the simplest semantically-correct answer may be to just remove final from a particular method that needs stubbing.

OTHER TIPS

I believe that using the final keyword is a great way to make it clear to future development teams that a specific method or class was intentionally not overridable. These limitations also bother me. Modern web containers also proxy pooled beans (etc.) and the same problem occurs there.

I would suggest looking into PowerMock. They provide an implementation that plugs into Mockito very nicely.

https://code.google.com/p/powermock/

-- EDIT --

For fear of starting a holy war, I would also like to say that, generally, you should test the exposed API in an interface and any final methods would be tested indirectly through that interface. However, it is useful to get in a little deeper if you have a high-risk method.

I find final keywords useful on methods when you don't other programmers to override the method.

Take for instance I had a trigometery class that found the hypotenuse of a right triangle by the 2 sides is the law square root of side a to the power of 2 plus side b to the power of 2. That's a mathematical law. To stop programmer's from overriding it and possibly making a mistake. make the method final

public class Trig
{
     public final double hytpotenuseOfRightTriangle(double sideA, double sideB)
     {
         return Math.sqrt(Math.pow(sideA, 2) + Math.pow(sideB, 2));
     }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top