2

I have two classes:

public class BaseClass <T> {
  private final T config;
  ...
  @NotNull
  public final T getConfig() {
    return config;
  }
}

public class DerivedClass extends BaseClass<MyConfig> {
  ...
}

And a test:

...
MyConfig myConfig = mock(MyConfig.class);
DerivedClass child = mock(DerivedClass.class);
when(child.getConfig()).thenReturn(myConfig); // this line generates the error

I get an error that getConfig() is returning null, rather than myConfig. I have other method calls to the same mock object working as expected with the when/return pattern, so I played around with the polymorphism. When I removed the final restriction on the method and overrode it in the derived class (just calling the super version), the mock worked properly.

I don't want to have to redesign the product code, and reduce the rigidity of the API, for a test, so the inheritance change above isn't an acceptable solution. How can I mock out the call to the superclass' method?

kwiqsilver
  • 1,017
  • 2
  • 11
  • 24
  • "Mock an inherited method" -- you could always make rude comments about its parentage, but that wouldn't be politically correct (sorry, couldn't resist the title :-) – Jim Garrison Jun 08 '16 at 20:43

2 Answers2

4

From Mockito's FAQ:

What are the limitations of Mockito?
[...]

  • Cannot mock final methods - their real behavior is executed without any exception. Mockito cannot warn you about mocking final methods so be vigilant.

[...]

For this, you need an extension like PowerMock. See this question for a working example. A throughout description can be found in PowerMock's documentation

Community
  • 1
  • 1
Turing85
  • 18,217
  • 7
  • 33
  • 58
  • 2
    Hint: one should at least mention that **PowerMock** has a **lot** of disadvantages. I would never recommend it to another person without a good dose of "normally you shouldn't be using this at all". – GhostCat Jun 09 '16 at 06:41
0

Unfortunately you can't mock final methods. But a word of warning: turning to PowerMock is not the answer to this problem. To the contrary: turning to PowerMock means entering a realm that shouldn't be entered without a lot of careful preparation.

PowerMock manipulates your byte code to allow you to override final or static methods. This means it will expose you to a huge variety of strange and bizarre problems; very often for no good reason; but with a good chance of wasting a lot of time hunting for "bugs" that have nothing to do with your code under test. Another big problem with PowerMock is that it renders most of the "coverage" frameworks useless (because those frameworks also manipulate bytecode ...)

So in your case: actually, it is good design to make that method final. As this emphasizes the Open/closed principle. So, from a conceptual points, there are two options to "fix" this:

a) you allow for dependency injection of that "config" object (for example by providing a protected constructor taking a "config")

b) you remember FCoI and avoid doing the baseclass/subclass thing altogether

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Bertrand Meyer (the creator of the "open-closed" principle) wrote (I can't seem to find it now, sorry) strongly against programming languages (like C++) where methods are non-overridable (not virtual) by default, or that even allow methods to be `final`, because that would *prevent* the application of OCP. So, while it *is* good design to make methods and classes `final`, it totally does not emphasize OCP. Rather, it emphasizes the "favor composition over inheritance" principle of GoF. – Rogério Oct 13 '16 at 21:41
  • How do you **close** a class for **modification** if you have no mean to prevent a subclass to overwrite a certain method?! The typical use case for OCP is when you have an abstract base class that provides one/more final methods to be called ...that themselves call abstract methods. If those methods would not be final, you could change that behavior on subclasses. – GhostCat Oct 14 '16 at 06:44
  • Actually, no, in OCP (as described in Meyer's book and in [Robert Martin's article](https://www.cs.duke.edu/courses/fall07/cps108/papers/ocp.pdf)) a class that is "closed" is merely one that has been put into production and which therefore shouldn't be modified anymore under penalty of breaking client code. Note this is what the authors say; I find this principle completely wrong and outdated. In the OCP author's view, a class should remain "open for extension", that is, it should *not* be declared `final` or have any of its non-`private` methods be declared as `final` either. – Rogério Oct 14 '16 at 14:50