@InjectMocks,构造函数或初始化块引发异常 [英] @InjectMocks, the constructor or the initialization block threw an exception
问题描述
当我使用@InjectMocks
时,发生了异常.我的代码如下所示:
When I use @InjectMocks
, an exception was occurred. My code is shown below:
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,有人可以帮助我吗?
it will throw an NPE, can someone help me?
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.
推荐答案
这种观念告诉你的东西...
What this exeception is telling you...
您尚未在字段声明中提供实例
You haven't provided the instance at field declaration
换句话说,你没有写...
In other words, you did not write...
@InjectMocks
A a = new A("foobar", 123);
这将是完全可以接受的,并且可能会解决您的问题.请记住,此时不会对模拟进行初始化,因此如果您确实需要在其中放置示例String
和int
,则很好,但是如果您需要在此处放置模拟,则可以.换句话说,如果您有一个使用X的构造函数,并且您将在此处编写新的A(x)
,则x将为null,因为尚未处理@Mock
批注.
This would be completely acceptable and will probably solve your problem. Please remember that mocks will NOT be initialized at that point, so it's fine if you really need an example String
and int
there, but not if you need to put mocks there. In other words, if you had a constructor that took an X and you would write new A(x)
here, x would be null, since the @Mock
annotation would not have been processed yet.
所以我试图构造实例
so I tried to construct the instance
因为没有实例(因为您没有提供实例),所以它试图创建一个实例,但是...
Because there was no instance (because you didn't provide one) it tried to create one, but...
但是,构造函数或初始化块引发了一个异常:null
However, the constructor or the initialization block threw an exception: null
因此,您的构造函数将引发null.好像您的someMethodCall
依赖于给定的参数(端口,最有可能不是空值),但是由于它们是String
和int
,因此Mockito不知道在那里要使用什么值.由于port
是原始类型,而Mockito并未专门处理这些类型,因此问题可能出在这里-Mockito会尝试在其中放置null,这将引发异常.
So, your constructor throws null. Seems like your someMethodCall
relies on the arguments (port, most likely) given not to be null, but since they are String
and int
, Mockito has no idea what values to use there. Since port
is a primitive type and Mockito does not handle those specifically, the problem is probably there - Mockito will try to put null there, which will throw an exception.
例如,如果您的构造函数匹配X和Y,则Mockito可能会尝试将模拟放置在此处,但事实并非如此.构造函数需要String
和int
,并且没有模拟,因此Mockito只能使用默认值,而默认值是null
,这对于port
来说是个问题(由于int
).
If your constructor matched X and Y, for example, Mockito would probably try to put the mocks there, but it doesn't. The constructor wants String
and int
and there are no mocks for them, so Mockito can only use default values and those are null
, which is a problem in case of port
(because of int
).
那么,解决方案是什么?
So, what's the solution?
1)要么使构造函数为null安全的,然后允许在其中提供null端口(并确保ip字符串也以null安全的方式进行处理).
1) Either make your constructor null-safe, allowing to give a null-port there (and make sure that the ip string is also handled in a null-safe way).
2)使用您不使用的东西:
2) Use the thing you didn't use:
@InjectMocks
A a = new A("foobar", 123);
在任何情况下,都不需要在构造函数中包含所有依赖关系,Mockito会很好地将它们直接注入字段中.因此,为X和Y添加另一个构造函数不是真正的解决方案.当然,通常,构造函数注入优于字段注入,但这是另一个主题.
In any case, it is not required to have all the depedencies in the constructor, Mockito will do fine injecting them into fields directly. So adding another constructor for X and Y is not a real solution. Of course, generally, constructor injection is preferable over field injection, but that's another topic.
As for your question about which constructor: The documentation says this...
选择最大的构造函数,然后仅使用在测试中声明的模拟来解析参数
the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only
似乎Mockito不知道如何处理构造函数中的原始字段,真可惜.
Seems that Mockito does not know how to handle primitive fields in constructors, what a shame.
这篇关于@InjectMocks,构造函数或初始化块引发异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!