Quarkus测试中Singleton转ApplicationScoped失败问题求助
问题分析与解决方案
问题原因
你的场景中@InjectMock(convertScopes = true)失效,核心原因是RestClient的Singleton作用域是通过application.properties配置项声明的,而非直接在接口上用注解标注。Quarkus的@InjectMock的convertScopes参数仅能识别并转换通过注解(比如@Singleton)声明的作用域,对配置文件中动态设置的作用域无法处理,因此仍然会识别到原Singleton作用域,触发CDI作用域校验错误。
解决方案
方案1:将RestClient的作用域改为注解声明(推荐)
把application.properties中的作用域配置移除,直接在RpoService接口上添加@Singleton注解:
@Path("api/rpo/registerdata/public/{filename}") @RegisterRestClient(configKey = "gpo.upload") @ClientHeaderParam(name = "Authorization", value = "{pe.dev.rpo.gpo.JwtStore.getBearer}") @Singleton // 直接用注解声明作用域 public interface RpoService { @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) Response upload(InputStream inputStream, @PathParam("filename") String filename); }
同时删除application.properties中的对应配置:
# 删除这一行 # gpo.upload/mp-rest/scope=javax.inject.Singleton
这样@InjectMock(convertScopes = true)就能正常识别并将Singleton转换为ApplicationScoped,Mock就能正常注入。
方案2:自定义Mock实现类替代RestClient
如果必须保留配置文件中的作用域设置,可以创建一个Mock实现类,通过Quarkus的@Mock注解替换原RestClient:
- 创建Mock实现类:
@Mock @ApplicationScoped @RegisterRestClient(configKey = "gpo.upload") public class MockRpoService implements RpoService { @Override public Response upload(InputStream inputStream, String filename) { // 这里可以根据测试需求返回预设的Response,或者用Mockito增强 Response mockResponse = Mockito.mock(Response.class); Mockito.when(mockResponse.getStatus()).thenReturn(201); return mockResponse; } }
- 在测试类中直接注入这个Mock类(或者依然注入原接口,Quarkus会自动替换为Mock实现):
@QuarkusTest public class ExportServiceTest { @Inject ExportService exportService; @Inject @RestClient RpoService ax; // 此时注入的是MockRpoService实例 @Test void test_upload() throws IOException { File f = File.createTempFile("some-prefix", "some-ext"); Path p = f.toPath(); FileInputStream inputStream = new FileInputStream(f); String fileName = "randomstring"; exportService.uploadDelete(p, fileName); assertThat(ax.upload(inputStream, fileName).getStatus()).isEqualTo(201); f.deleteOnExit(); } }
如果需要动态设置Mock行为,可以在测试类中用Mockito的spy包装这个Mock实例:
@Inject @RestClient RpoService ax; @BeforeEach void setup() { ax = Mockito.spy(ax); } @Test void test_upload() throws IOException { // 动态修改Mock行为 Response customResponse = Mockito.mock(Response.class); Mockito.when(customResponse.getStatus()).thenReturn(400); Mockito.when(ax.upload(any(InputStream.class), anyString())).thenReturn(customResponse); // 测试逻辑... }
方案3:升级Quarkus版本
部分旧版本的Quarkus存在@InjectMock(convertScopes = true)对配置式作用域支持不足的问题,建议升级到Quarkus 2.16.x及以上版本,该问题在后续版本中已被修复。
内容的提问来源于stack exchange,提问作者Gerard
相关产品推荐
相关产品推荐

