我的代码如下:
public class RealWorldBoImpl extends AbstractBoImpl<T> implements SomeBo{}
和
@RunWith(PowerMockRunner.class)
@PrepareForTest({RealWorldBoImpl.class})
public class RealWorldBoImplTest {
@InjectMocks
private RealWorldBoImpl realWorldBo;
@Mock
private RealWorldDAO realWorldDAO;
@Test
public void changeStatusMainSubString() throws Exception {
long id = 1L;
}
在这种情况下,Realworlddao不能注入Realworldbo。但是当我删除preparfortest时,它可以正常工作。
我也尝试了其他课程,它们效果很好。似乎Realworldboimpl是特殊的,当做准备时,它不会正确注入模拟。
我调试了此代码,并发现,在org.mockito.internal.util.util.reflection.fieldinitializer#checkParametrized,constructor.getParametertypes()不是空的,并且具有构造函数,并带有类indionaleleloadclass。
。private void checkParameterized(Constructor<?> constructor, Field field) {
if(constructor.getParameterTypes().length == 0) {
throw new MockitoException("the field " + field.getName() + " of type " + field.getType() + " has no parameterized constructor");
}
}
但我不知道Realworldboimpl有什么特别之处。它只是扩展了父类并实现接口。这有关系吗?
当PowerMock准备一个具有Object
以外的超级阶级的类时,它将构造函数添加到类中,该类构建函数以org.powermock.core.IndicateReloadClass
类型的参数。
为什么PowerMock这样做?PowerMock通过这种机制实现了超类构造函数。在您的情况下,因为RealWorldBoImpl
源自AbstractBoImpl
PowerMock将以下构造函数添加到RealWorldBoImpl
,AbstractBoImpl
类:
public RealWorldBoImpl(IndicateReloadClass var1) {
super(var1);
}
public AbstractBoImpl(IndicateReloadClass var1) {
super(); //assuming the parent class is Object otherwise super(var1)
}
并将RealWorldBoImpl
的默认NO-ARG构造函数更改为以下:
public RealWorldBoImpl() {
Object var1 = MockGateway.constructorCall(Desc.getClazz("org.example.RealWorldBoImpl"),
new Object[0], Desc.getParams("()V"));
if (var1 != MockGateway.PROCEED) {
super((IndicateReloadClass)null);
} else {
super();
}
}
那是PowerMock部分,现在让我们进入Mockito部分。
Mockito具有两种注入策略(MockInjectionStrategy
):ConstructorInjection
和PropertyAndSetterInjection
。
ConstructorInjection
使用构造函数注入模拟,如果注射者至少具有一个非默认构造函数(一种至少采用一个参数的构造函数),则使用。如果注射者只有一个no-arg构造函数,则Mockito使用PropertyAndSetterInjection
使用Setter方法,如果没有Setter方法,则它可以通过反射设置字段的值直接注入模拟。
在您准备RealWorldBoImpl
类时,您的构造函数带有一个参数,Mockito使用ConstructorInjection
通过PowerMock添加的构造函数将模拟注入对象(并且由于没有类型IndicateReloadClass
的模拟,Mockito将NULL传递到NULL构造函数,但这并不重要,因为构造函数什么都不做),因此没有模拟。
那么如何解决问题?如果您要注入多个模拟,请在Injextee类中添加一个构造函数,并具有与要注入的模拟数量一样多的参数。只要您拥有一个多个参数的构造函数,注射剂就可以正常工作,否则您的注射者类应该具有Object
作为超类。
如果您只有一个模拟,则可以向构造函数添加一个虚拟参数,以使Mockito选择您的构造函数,而不是PowerMock添加的构造函数:
public RealWorldBoImpl(RealWorldDAO realWorldDAO, String dummy) {
this.realWorldDAO = realWorldDAO;
}