在 Groovy 测试期间 Spring Autowire bean NullPointerException 但在运行时工作正常
Posted
技术标签:
【中文标题】在 Groovy 测试期间 Spring Autowire bean NullPointerException 但在运行时工作正常【英文标题】:Spring Autowire bean NullPointerException during Groovy tests but works fine during Runtime 【发布时间】:2021-09-06 10:16:53 【问题描述】:我正在使用 prometheus 库来获取我的 Spring Boot 应用程序 (REST API) 的指标。我正在使用库 io.prometheus.simpleclient:0.4.0
并将它包含在我的 Maven pom.xml 中。我正在使用Counter
和@Autowiring(我已经尝试过字段和构造函数注入)它到我自己的类之一,就像这样
MyCustomMetricsClass.java
@Component
public MyCustomMetricsClass
@Autowire
private Counter counterBean;
public void myOwnMetricsMethod()
counterBean.inc();
// do some stuff
那么,我正在 @Autowiring 这个MyCustomMetricsClass
到我的服务类 MyServiceClass.java
中,当我使用 Spring 在本地运行我的 API 时它似乎运行良好在端口 8080 (localhost:8080) 上启动嵌入式 tomcat。我可以点击端点,并且在执行器端点(localhost:8080/actuator/metrics)上正确报告了指标。例如
MyServiceClass.java
public MyServiceClass
@Autowire
private MyCustomMetricsclass myMetrics;
public void genericServiceMethod()
myMetrics.MyOwnMetricsMethod(); // NULL POINTER EXCEPTION ONLY DURING TEST SCOPE (GROOVY)
问题是,当我运行mvn install
(触发我编写的本地 Groovy 单元测试)时,我不断收到 NULL POINTER EXCEPTION。使用调试器,我可以调试 Groovy 单元测试,并在我的 Service 类中看到 myMetrics
变量为 NULL。但是我不明白为什么它在运行时可以正常工作,而且我已经将MyCustomMetricsClass
注释为 @Component 注释,所以它应该是一个被 Spring Component scan 扫描的 bean。
这是一个多模块项目;结构如下
my-project (root, contains root pom.xml)
- my-api (module, contains RestController. has its own pom.xml)
- my-service (module. contains service classes, has its own pom.xml)
- my-model (module, contains all POJO/DTO model classes, has its own pom.xml)
我是否缺少对类路径的依赖?为什么它在运行时有效,但在测试期间无效? (我所有的依赖项都应该有默认范围)自动装配被破坏了吗?
【问题讨论】:
【参考方案1】:你能分享你的单元测试代码吗?
猜测一下,您使用的是一个模拟框架,也许是 Mockito?
如果这个假设成立,请记住,您的单元测试不会运行完整的 Spring 上下文,因此不会发生自动装配。您需要为自动装配的组件注入模拟。
例如:
@RunWith(MockitoJUnitRunner.class)
public class MyServiceClassTest
@Mock
private MyCustomMetricsClass myCustomMetricsClass;
@InjectMocks
private MyServiceClass myServiceClass;
@Test
public void shouldDoTesting()
myServiceClass. genericServiceMethod();
verify(myMetrics).MyOwnMetricsMethod();
【讨论】:
谢谢。我正在使用 Groovy/Spock。你是对的,我没有嘲笑我的服务类中使用的上述“myMetrics”变量,但由于某种原因,它仍然没有被正确地嘲笑我嘲笑它就像:def myCustomMetricsMock = Mock(MyCustomMetricsClass.class)跨度> 谢谢,我在 Groovy 中嘲笑它,但仍然得到 NPE。我没有意识到在 groovy 中,或者至少在我们的代码库中,我们需要在 Test 下模拟整个类,然后将所有模拟设置为引用该类的所有成员变量/字段。当我这样做时,NPE 消失了,一切都编译好了。我会给你最好的答案,因为你指出了我正确的方向,谢谢!以上是关于在 Groovy 测试期间 Spring Autowire bean NullPointerException 但在运行时工作正常的主要内容,如果未能解决你的问题,请参考以下文章