NotAMockException 在尝试对 Environment 的 SpyBean 方法进行模拟时发生

huangapple go评论66阅读模式
英文:

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,以便进行注入。因此,它无法像ApplicationContextBeanFactory一样被模拟或监视,这些都是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.

huangapple
  • 本文由 发表于 2023年6月1日 19:32:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定