NotAMockException when trying to mock a method on a SpyBean of Environment

498 Views Asked by At

In an integration test (@SpringBootTest) class I declare a spyBean:

@SpyBean
private Environment environment;

In a test I try to mock one method:

doReturn(true).when(environment).acceptsProfiles(Profiles.of("prod"));

However, I get the following error:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();

How can I properly mock the method?

1

There are 1 best solutions below

4
Jonasz On BEST ANSWER

Environment is part of the essential configuration used to create Spring context while the application is started. The environment object is created before the context is prepared and only later registered as a bean within the context to enable injection. Because of that it cannot be mocked or spied on, similarly to ApplicationContext or BeanFactory, which are basic Spring context building blocks as well.

You can verify that yourself, using a debugger and the Spring Boot open-sourced code - look specifically at this part (run method in the SpringApplication class). The Environment object is prepared before the context is created and the mock/spy beans are created and injected during context refresh after its creation. To verify that you could simply create a class, mark it with the @SpyBean annotation in a test, set a breakpoint in the constructor and run the test with debugging. Whether Spring testing library should inform about the incorrect usage of @MockBean/@SpyBean on the interfaces/classes that cannot be mocked or spied on is a different matter and you could ask that question or propose adding that in an appropriate GitHub repository.

Regarding the solution to the problem (I think) you're trying to solve: it looks like you could use the @ActiveProfiles annotation to enable a specific profile in your test class or use any other way of setting an active Spring profile.