35

The following line seems to mock all static methods in the class:

MockedStatic <Sample> sampleMock = Mockito.mockStatic( Sample.class );
sampleMock.when( () -> Sample.sampleStaticMethod( Mockito.any( String.class ) ) ).thenReturn( "response" );

Is it possible to mock just one static method in a class?

Kumar
  • 1,023
  • 1
  • 10
  • 23
  • I updated my answer [here](https://stackoverflow.com/a/63840969/292728) to include more information that I think will help with this – Kevin K Sep 11 '20 at 05:21
  • @KevinK, I tried your sample and while the method returned what its supposed to return, it was actually called despite being mocked. Is that expected? Did it happen in your sample as well? – Kumar Sep 11 '20 at 08:36
  • 1
    @Kumar it is expected reading the docs. The solution would be to use `doReturn().when()` syntax but is still not supported, check the details on my answer. – Marc Sep 11 '20 at 09:49

1 Answers1

57

By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods excluding only one.

For example given the class Sample:

class Sample{
    static String method1(String s) {
        return s;
    }
    static String method2(String s) {
        return s;
    }
}

If we want to mock only method1:

@Test
public void singleStaticMethodTest(){
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
        assertEquals("bar", Sample.method1("foo")); // mocked
        assertEquals("foo", Sample.method2("foo")); // not mocked
    }
}

Be aware that the real Sample.method1() will still be called. From Mockito.CALLS_REAL_METHODS docs:

This implementation can be helpful when working with legacy code. When this implementation is used, unstubbed methods will delegate to the real implementation. This is a way to create a partial mock object that calls real methods by default. ...

Note 1: Stubbing partial mocks using when(mock.getSomething()).thenReturn(fakeValue) syntax will call the real method. For partial mock it's recommended to use doReturn syntax.

So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn (as the doc suggests) but for static methods is still not supported:

@Test
public void singleStaticMethodTest() {
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        doReturn("bar").when(mocked).method1(anyString()); // Compilation error!
        //...
    }
}

About this check this issue.

Marc
  • 2,738
  • 1
  • 17
  • 21
  • did you actually try this method yourself? I tried and it ended up calling the static method that was mocked. Let me try it out in a sample project instead of the legacy project I'm using now. – Kumar Sep 11 '20 at 06:59
  • Yes I tried myself, using the class `Sample` I provided. It shouldn't be a problem to reproduce it. Let me know otherwise. – Marc Sep 11 '20 at 07:17
  • 1
    I tried it and the mocked method returns the expected response. But I also noticed that the mocked method is being called (despite the response being what is specified in the test). Is this expected? – Kumar Sep 11 '20 at 08:34
  • 2
    @Kumar It seems to be the expected behavior from the docs (see my updated answer). So the static method is stubbed but still called. The question now is how to use `doReturn` syntax for a static method to ensure that the real stubbed method is not called. – Marc Sep 11 '20 at 09:17
  • ...However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods... use `@spy` when you want to test actual method with their internal. – Vishwa Ratna Sep 11 '20 at 11:01
  • Nice answer. Still working with Mockito 4.6.1 – Thomas Pires Jun 30 '22 at 11:43