Quarkus单元测试中@InjectMock注入Logger出现NPE如何解决?
问题原因
该空指针异常并非Quarkus本身的bug,属于@InjectMock使用方式不当导致的问题:
Quarkus内置的Logger生产者创建Logger实例时,需要读取注入点对应的目标类元数据,来生成对应类的专属Logger实例。直接在测试类中声明无任何限定符的@InjectMock Logger logger,触发生产者逻辑时会出现注入点元数据缺失,进而抛出空指针异常。
解决方法
可选用以下两种方案实现日志输出验证:
手动Mock Logger并注入被测类(轻量推荐)
无需依赖Quarkus的注入能力实现Logger mock,直接用Mockito手动创建mock实例,再注入到被测的ApplicationExceptionMapper中即可,示例代码如下:import org.jboss.logging.Logger; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.test.util.ReflectionTestUtils; import javax.ws.rs.core.Response; @QuarkusTest public class ApplicationExceptionMapperTest { ApplicationExceptionMapper mapper = new ApplicationExceptionMapper(); Logger mockLogger = Mockito.mock(Logger.class); @BeforeEach void init() { // 若mapper的Logger为字段注入,可通过反射工具类赋值,也可通过构造方法传入mock实例 ReflectionTestUtils.setField(mapper, "logger", mockLogger); } @Test void simpleTest() { Response response = mapper.toResponse(new IllegalArgumentException()); Assertions.assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus()); Mockito.verify(mockLogger, Mockito.times(1)).error(Mockito.anyString(), Mockito.any(IllegalArgumentException.class)); } }为Mock的Logger添加匹配限定符
如果要保留@InjectMock的使用方式,需要为mock的Logger添加和被测类中Logger一致的@Named限定符,取值为被测类的全限定类名:import org.jboss.logging.Logger; import javax.inject.Named; import javax.ws.rs.core.Response; @QuarkusTest public class ApplicationExceptionMapperTest { // 替换括号内的值为你实际的ApplicationExceptionMapper全限定类名 @InjectMock @Named("com.your.business.package.ApplicationExceptionMapper") Logger logger; @Inject ApplicationExceptionMapper mapper; @Test void simpleTest() { Response response = mapper.toResponse(new IllegalArgumentException()); Assertions.assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus()); Mockito.verify(logger, Mockito.times(1)).error(Mockito.anyString(), Mockito.any(IllegalArgumentException.class)); } }
内容的提问来源于stack exchange,提问作者Mani76
相关产品推荐
相关产品推荐

