How to mock a final class with mockito

2019-01-01 15:26发布

I have a final class, something like this:

public final class RainOnTrees{

   public void startRain(){

        // some code here
   }
}

I am using this class in some other class like this:

public class Seasons{

   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain(){

        rain.startRain();

    }
}

and in my JUnit test class for Seasons.java I want to mock the RainOnTrees class. How can I do this with Mockito?

19条回答
不再属于我。
2楼-- · 2019-01-01 15:51

Give this a try:

Mockito.mock(SomeMockableType.class,AdditionalAnswers.delegatesTo(someInstanceThatIsNotMockableOrSpyable));

It worked for me. "SomeMockableType.class" is the parent class of what you want to mock or spy, and someInstanceThatIsNotMockableOrSpyable is the actual class that you want to mock or spy.

For more details have a look here

查看更多
查无此人
3楼-- · 2019-01-01 15:52

Solutions provided by RC and Luigi R. Viggiano together is possibly the best idea.

Although Mockito cannot, by design, mock final classes, the delegation approach is possible. This has its advantages:

  1. You are not forced to change your class to non-final if that is what your API intends in the first place (final classes have their benefits).
  2. You are testing the possibility of a decoration around your API.

In your test case, you deliberately forward the calls to the system under test. Hence, by design, your decoration does not do anything.

Hence you test can also demonstrate that the user can only decorate the API instead of extending it.

On a more subjective note: I prefer keeping the frameworks to a minimum, which is why JUnit and Mockito are usually sufficient for me. In fact, restricting this way sometimes forces me to refactor for good as well.

查看更多
浪荡孟婆
4楼-- · 2019-01-01 15:53

Just to follow up. Please add this line to your gradle file:

testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'

I have tried various version of mockito-core and mockito-all. Neither of them work.

查看更多
旧人旧事旧时光
5楼-- · 2019-01-01 15:57

Another workaround, which may apply in some cases, is to create an interface that is implemented by that final class, change the code to use the interface instead of the concrete class and then mock the interface. This lets you separate the contract (interface) from the implementation (final class). Of course, if what you want is really to bind to the final class, this will not apply.

查看更多
骚的不知所云
6楼-- · 2019-01-01 15:57

This can be done if you are using Mockito2, with the new incubating feature which supports mocking of final classes & methods.

Key points to note:
1. Create a simple file with the name “org.mockito.plugins.MockMaker” and place it in a folder named “mockito-extensions”. This folder should be made available on the classpath.
2. The content of the file created above should be a single line as given below:
mock-maker-inline

The above two steps are required in order to activate the mockito extension mechanism and use this opt-in feature.

Sample classes are as follows:-

FinalClass.java

public final class FinalClass {

public final String hello(){
    System.out.println("Final class says Hello!!!");
    return "0";
}

}

Foo.java

public class Foo {

public String executeFinal(FinalClass finalClass){
    return finalClass.hello();
}

}

FooTest.java

public class FooTest {

@Test
public void testFinalClass(){
    // Instantiate the class under test.
    Foo foo = new Foo();

    // Instantiate the external dependency
    FinalClass realFinalClass = new FinalClass();

    // Create mock object for the final class. 
    FinalClass mockedFinalClass = mock(FinalClass.class);

    // Provide stub for mocked object.
    when(mockedFinalClass.hello()).thenReturn("1");

    // assert
    assertEquals("0", foo.executeFinal(realFinalClass));
    assertEquals("1", foo.executeFinal(mockedFinalClass));

}

}

Hope it helps.

Complete article present here mocking-the-unmockable.

查看更多
残风、尘缘若梦
7楼-- · 2019-01-01 15:57

Use Powermock. This link shows, how to do it: https://github.com/jayway/powermock/wiki/MockFinal

查看更多
登录 后发表回答