@InjectMocks,构造函数或初始化块抛出异常

新手上路,请多包涵

当我使用 @InjectMocks 时,发生了异常。我的代码如下所示:

 class A {
    private X x;
    private Y y;
    public A(String ip, int port) {
       this(someMethodCall(ip, port)); //
    }

    private A(X x) {
        this.x = x;
        this.y = new Y();
    }
}
UT:
public class ATest() {
    @InjectMocks A a;
    @Mock X x;
    @Mock Y y;
    @Test ...
}

它会抛出 NPE,有人可以帮助我吗?

org.mockito.exceptions.base.MockitoException: Cannot instantiate @InjectMocks field named 'channel' of type 'class Juinit3.Channel'. You haven't provided the instance at field declaration so I tried to construct the instance. However, the constructor or the initialization block threw an exception: null.

原文由 dingrui 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.8k
1 个回答

这个异常告诉你什么……

您没有在字段声明中提供实例

换句话说,你没有写…

 @InjectMocks
A a = new A("foobar", 123);

这是完全可以接受的,并且可能会解决您的问题。请记住,此时不会初始化模拟,因此如果您真的需要一个示例 Stringint 就可以了,但如果您需要将模拟放在那里则不需要。换句话说,如果您有一个采用 X 的构造函数,并且您将在此处编写新的 A(x) ,则 x 将为空,因为 @Mock 注释尚未处理。

所以我试图构建实例

因为没有实例(因为你没有提供)它试图创建一个,但是……

但是,构造函数或初始化块抛出异常:null

所以,你的构造函数抛出 null。似乎你的 someMethodCall 依赖于参数(端口,最有可能)不为空,但因为它们是 Stringint to在那里使用什么值。由于 port 是原始类型并且 Mockito 没有专门处理这些类型,问题可能就在那里 - Mockito 会尝试将 null 放在那里,这将引发异常。

例如,如果您的构造函数匹配 X 和 Y,Mockito 可能会尝试将模拟放在那里,但事实并非如此。构造函数想要 Stringint 并且没有针对它们的模拟,因此 Mockito 只能使用默认值,这些是 null 中的问题,这是一个问题 port (因为 int )。

那么,解决方案是什么?

1)要么让你的构造函数空安全,允许在那里给一个空端口(并确保 ip 字符串也以空安全的方式处理)。

2)使用你没有使用的东西:

 @InjectMocks
A a = new A("foobar", 123);

在任何情况下,都不需要在构造函数中拥有所有依赖项,Mockito 可以将它们直接注入到字段中。因此,为 X 和 Y 添加另一个构造函数并不是真正的解决方案。当然,一般来说,构造函数注入优于字段注入,但这是另一个话题。

至于你关于哪个构造函数的问题: 文档 说这个……

选择最大的构造函数,然后仅使用在测试中声明的模拟来解析参数

编辑: 似乎 Mockito 不知道如何处理构造函数中的原始字段,真可惜。

原文由 Florian Schaetz 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题