英文:
NotAMockException when trying to mock a method on a SpyBean of Environment
问题
在一个集成测试 (@SpringBootTest)
类中,我声明了一个 spyBean
:
@SpyBean
private Environment environment;
在测试中,我尝试模拟一个方法:
doReturn(true).when(environment).acceptsProfiles(Profiles.of("prod"));
然而,我遇到了以下错误:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();
如何正确模拟这个方法?
英文:
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
得分: 2
Environment
是在应用程序启动时用于创建Spring上下文的重要配置的一部分。环境对象在上下文准备好之前创建,并且稍后才会在上下文中注册为一个bean,以便进行注入。因此,它无法像ApplicationContext
或BeanFactory
一样被模拟或监视,这些都是Spring上下文的基本构建块。
您可以使用调试器和Spring Boot的开源代码自行验证这一点 - 具体查看这部分(SpringApplication
类中的run
方法)。Environment
对象在上下文创建之前准备,模拟/监视的bean在上下文创建后的上下文刷新期间创建并注入。要验证这一点,您可以简单地创建一个类,将其标记为测试中的@SpyBean
注解,在构造函数中设置断点,然后以调试模式运行测试。关于Spring测试库是否应该通知关于在无法模拟或监视的接口/类上错误使用@MockBean
/@SpyBean
的问题,这是另一回事,您可以提出这个问题或在适当的GitHub存储库中提出建议。
关于解决问题的解决方案(我认为)你正在尝试解决的问题:看起来你可以使用@ActiveProfiles注解在测试类中启用特定配置文件,或者使用其他设置活动Spring配置文件的方式。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论