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?
Environmentis 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 toApplicationContextorBeanFactory, 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 (
runmethod in theSpringApplicationclass). TheEnvironmentobject 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@SpyBeanannotation 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/@SpyBeanon 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.