45

I am getting the following exception when trying to mock the static method.

For SettingsUtility, static mocking is already registered in the current thread To create a new mock, the existing static mock registration must be deregistered

@Before
fun setUp() {
    mockStatic(SettingsUtility::class.java) {
        `when` { SettingsUtility.method(app) }.thenReturn { "" }}
}
Qumber Abbas
  • 560
  • 1
  • 4
  • 11

7 Answers7

73

The returned object's MockedStatic.close() method must be called upon completing the test or the mock will remain active on the current thread.

I am not sure if it is the same as how its done in Java. Hope this Java code snippet helps

private static MockedStatic<SettingsUtility> mockedSettings;

@BeforeAll
public static void init() {
    mockedSettings = mockStatic(SettingsUtility.class);
}

@AfterAll
public static void close() {
    mockedSettings.close();
}
WhiteShadow
  • 800
  • 2
  • 9
  • 22
Sudha Chinnappa
  • 793
  • 4
  • 10
31

Try doing this way, you will not get this error. It worked for me.

try(MockedStatic mocked = mockStatic(SettingsUtility.class)) {
        mocked.when(SettingsUtility::method).thenReturn("whatever you want");
    }
Rajesh Kumar
  • 389
  • 2
  • 7
17

Building on @Sudha 's answer. in Java you can use @BeforeClass and @AfterClass

private static MockedStatic<SettingsUtility> mockedSettings;

@BeforeClass
public static void init() {
    mockedSettings = mockStatic(mockedSettings.class);
}

@AfterClass
public static void close() {
    mockedSettings.close();
}
a fair player
  • 11,530
  • 9
  • 46
  • 48
  • `@BeforeClass` and `@AfterClass` are JUnit 4 constructs. JUnit 5 in java is what @sudha-chinnappa was showing. – gaoagong Sep 09 '22 at 21:24
7

Mockito Inline works differently than the Mockito hence the failure. So what needs to be done is initialise and close the mocks explicitly.

You need to initialise the mockedStatic for your class

private MockedStatic<YourClassWithStaticMethod> mockedStatic;

Then add below code in BeforeEach and AfterEach

@BeforeEach
  public void init() {
    mockedStatic = mockStatic(YourClassWithStaticMethod.class);
  }

@AfterEach
  public void cleanup() {
    mockedStatic.close();
  }

And now you can set the mocked expectations.

mockedStatic.when(YourClassWithStaticMethod::staticMethodToMock).thenReturn(yourReturnedMockedObject);
Sanjay Bharwani
  • 3,317
  • 34
  • 31
2

I tried below and worked for me.

MockedStatic mockedStatic = mockStatic(SettingsUtility.class)
mocked.when(SettingsUtility::method).thenReturn("any thing");
...........
//do all stuf

and at last close the mock

mockedStatic.close();
Null Pointer
  • 255
  • 1
  • 5
  • 21
0

Always use MockedStatic in function context inside try() that auto-closes it rather than using it as private static class variable. Using it at a class level variable will result into these sort of error even if you close them in AfterAll or AfterEach.

Example -

try ( MockedStatic mockedYourClassStatic = Mockito.mockStatic(YourClass.class) ) { ... }

Also you can refer to this -

https://github.com/mockito/mockito/blob/4767db122f95e5302ad6a60a6efaa69f9d7e6cb1/subprojects/inline/src/test/java/org/mockitoinline/StaticMockTest.java

Manish Sinha
  • 221
  • 1
  • 2
  • 6
0

@sudha-chinnappa answer is the one. Use:

@AfterAll
public static void close() {
  mockedSettings.close();

}

To close the static mocking

Rodrigo
  • 11
  • 1
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34761131) – Himanshu Bansal Aug 03 '23 at 19:31