在 Quarkus 测试中将值注入私有字段

问题描述

我正在尝试使用 Quarkus 应用程序中的 FieldSetter 将值设置为我的测试类中的私有字段(Quarkus 版本:1.5.2.Final 和 JDK 版本:11)

主类

@ApplicationScoped
public class TokenService{
    @Inject @RestClient RestClientInterface client;

    private String someVariable;

    public String someMethod(){}
}

测试类

@QuarkusTest
public class TokenServiceTest{
    @Inject TokenService service;
    @InjectMock @RestClient RestClientInterface client;

    @Test
    public void someMethodtest(){
       FieldSetter.setField(service,"someVariable","someValue");
    }
}

但是 FieldSetter 抛出 NoSuchField 错误。请帮忙。 也试过

service.getClass().getdeclaredField("someVariable")

但同样的问题。

提前致谢。

解决方法

TokenService 类是 @ApplicationScoped。这意味着如果您在某处@Inject 它,则不会直接注入该类的实例。相反,注入的是所谓的客户端代理,它是原始类的子类。该子类负责在每次方法调用时查找正确的实例(并将调用转发给实例)。

这个子类自然声明someVariable。这就是 getDeclaredField("someVariable") 失败的原因。我假设 FieldSetter 来自 Mockito —— 在这种情况下,它会做同样的事情并且由于同样的原因失败。

您可以将 TokenService 设为 @Singleton -- 在这种情况下,没有客户端代理并直接注入实例 -- 或者使用客户端代理是子类的知识并简单地查看在一个超类。或者——这可能是最好的——重新设计你的代码,这样你就不必从外部更改 private 字段。无论如何,这是一种代码气味。