kwiqsilver
kwiqsilver

Reputation: 1027

Mock an inherited final method

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?

Upvotes: 2

Views: 1478

Answers (2)

GhostCat
GhostCat

Reputation: 140427

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

Upvotes: 0

Turing85
Turing85

Reputation: 20185

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

Upvotes: 4

Related Questions