Final method mocking

75,228

Solution 1

There is no support for mocking final methods in Mockito.

As Jon Skeet commented you should be looking for a way to avoid the dependency on the final method. That said, there are some ways out through bytecode manipulation (e.g. with PowerMock)

A comparison between Mockito and PowerMock will explain things in detail.

Solution 2

From the Mockito 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.

Solution 3

You can use Powermock together with Mockito, then you do not need to subclass B.class. Just add this to the top of your test class

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)

@PrepareForTest instructs Powermock to instrument B.class to make the final and static methods mockable. A disadvantage of this approach is that you must use PowerMockRunner which precludes use of other test runners such as the Spring test runner.

Solution 4

Mockito 2 now supports mocking final methods but that's an "incubating" feature. It requires some steps to activate it which are described here: https://github.com/mockito/mockito/wiki/What's-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods

Solution 5

Mockito 2.x now supports final method and final class stubbing.

From the docs:

Mocking of final classes and methods is an incubating, opt-in feature. This feature has to be explicitly activated by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:

mock-maker-inline

After you create this file you can do:

final class FinalClass {
  final String finalMethod() { return "something"; }
}

FinalClass concrete = new FinalClass(); 

FinalClass mock = mock(FinalClass.class);
given(mock.finalMethod()).willReturn("not anymore");

assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

In subsequent milestones, the team will bring a programmatic way of using this feature. We will identify and provide support for all unmockable scenarios.

Share:
75,228
Stan Kurilin
Author by

Stan Kurilin

My full name is Stanislav Vladimirovich Kurilin

Updated on July 20, 2022

Comments

  • Stan Kurilin
    Stan Kurilin almost 2 years

    I need mock some class with final method using mockito. I have wrote something like this

    @Test
    public void test() {
        B b = mock(B.class);
        doReturn("bar called").when(b).bar();   
        assertEquals("must be \"overrided\"", "bar called", b.bar());
        //bla-bla
    }
    
    
    class B {
        public final String bar() {
            return "fail";
        }
    }
    

    But it fails. I tried some "hack" and it works.

       @Test
       public void hackTest() {
            class NewB extends B {
                public String barForTest() {
                    return bar();
                }
            }
            NewB b = mock(NewB.class);
            doReturn("bar called").when(b).barForTest();
            assertEquals("must be \"overrided\"", "bar called", b.barForTest());
        }
    

    It works, but "smells".

    So, Where is the right way?

    Thanks.

  • Jan Zyka
    Jan Zyka over 8 years
    This doesn't work for me. Added as adviced but still getting NullPointerException in the same way when not using the @RunWith and @PrepareForTest. Seems the class hasn't been intrumented for some reason.
  • mike rodent
    mike rodent over 7 years
    Thanks for this. Do you happen to know what the current state of verifying final methods is? Obviously I had a look in that page but it didn't seem to say anything...
  • WindRider
    WindRider over 7 years
    I'm not sure. Check out this: stackoverflow.com/questions/14292863/…
  • Vladyslav Nikolaiev
    Vladyslav Nikolaiev about 6 years
    Link seems to be broken
  • Cedric Reichenbach
    Cedric Reichenbach almost 6 years
    You should then mock with PowerMockito.mock, not Mockito.mock.
  • Cypress Frankenfeld
    Cypress Frankenfeld over 5 years
    Now that is only listed under Mockito 1.x Specific Limitations github.com/mockito/mockito/wiki/…. Perhaps you can mock final methods in Mockito 2.x?
  • Cypress Frankenfeld
    Cypress Frankenfeld over 5 years
    Yes, I just checked and you can now mock final methods in Mockito 2.x. I added how to do so in an answer: stackoverflow.com/a/53837478/382892
  • Cypress Frankenfeld
    Cypress Frankenfeld about 5 years
    This is out of date. Mockito 2.x supports final method mocking now (see the docs: github.com/mockito/mockito/wiki/…)
  • Cypress Frankenfeld
    Cypress Frankenfeld about 5 years
    Mockito now supports final method mocking in Mockito 2.x github.com/mockito/mockito/wiki/…
  • vmaldosan
    vmaldosan about 5 years
    I tried this approach with SpringRunner and worked for the specific use case I wanted, but making all mocks in the project inlined broke multiple tests in the project, all of them run with MockitoJUnitRunner. I could provide more details if somebody wanted to investigate further. For now I'll wait until that functionality is incorporated into the Mockito code base without altering all the mocks of the project.
  • Noel Yap
    Noel Yap over 4 years
    This answer is obsolete. Mockito now supports mocking final methods. See baeldung.com/mockito-final.
  • ThomasW
    ThomasW about 4 years
    Note that this method doesn't work for Android. github.com/mockito/mockito/issues/1173
  • spottedmahn
    spottedmahn about 4 years
  • Snekse
    Snekse about 4 years
    Be warned, this may slow down your tests