我有一个班级Dummy
。我注入3个变量。但是,其中一个不能注射,因为它是一个界面。所以我注入一个对象,其中一个方法返回所需的类型。
Class Dummy
{
private final Class1 class1;
private final Class2 class2
private final Interface1 interface1;
@Inject
Dummy(Class1 class1, Class2 class2, HelperClass helperclass)
{
this.class1 = class1;
this.class2 = class2;
this.interface1 = helperclass.somefunction();
}
}
HelperClass
的{{1}}会返回somefunction
的实例。
这是我的测试:
Interface1
但是,运行测试时@RunWith(MockitoJUnitRunner.class)
Class DummyTest
{
@Mock
private Class1 class1;
@Mock
private Class2 class2;
@Mock
private HelperClass helperclass;
@InjectMocks
private Dummy dummy;
@Before
public void start()
{
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
@Test
public void test()
{
// etc...
}
}
为空。我做错了什么?
答案 0 :(得分:6)
@InjectMocks
发生在@Before
注释之前。出于这个原因(以及other reasons),我建议完全不使用@InjectMocks
;只需使用真正的构造函数在@Before
方法中构建SUT类。
当您向测试类添加一些print语句时,此顺序很明显。我删除了所有Class1
和Class2
内容,因为它们不相关。请参阅此代码运行:
@RunWith(MockitoJUnitRunner.class)
public class DummyTest {
@Mock
private HelperClass helperclass;
@InjectMocks
private Dummy dummy;
@Before
public void start()
{
System.out.println("In @Before!");
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
@Test
public void test()
{
System.out.println("In @Test!");
}
public static class Dummy {
public final Interface1 interface1;
public final HelperClass helperclass;
@Inject
Dummy(HelperClass helperclass)
{
System.out.println("In dummy constructor!");
this.interface1 = helperclass.somefunction();
this.helperclass = helperclass;
}
}
private static class HelperClass {
Interface1 somefunction() {
return new Interface1() {};
}
}
private static interface Interface1 {
}
}
输出:
In dummy constructor!
In @Before!
In @Test!
如果您坚持使用@Mock
和@InjectMocks
,则可以尝试使用answer
参数:
@Mock(answer=Answers.RETURNS_MOCKS)
会使helperclass.somemethod()
返回模拟而不是null
。
老实说,它以这种方式工作并不奇怪。 Mockito
的作者真的不喜欢Partial Mocks / Stubs,并且明确地这样说in their documentation:
像往常一样,您将阅读部分模拟警告:通过将复杂性划分为单独的特定SRPy对象,面向对象编程更不能解决复杂性问题。部分模拟如何适应这种范式?好吧,它只是没有...部分模拟通常意味着复杂性已被移动到同一对象上的不同方法。在大多数情况下,这不是您想要设计应用程序的方式。
然而,在极少数情况下,部分模拟很方便:处理代码无法轻易更改(第三方接口,遗留代码的临时重构等)但是,我不会使用部分模拟新的,测试驱动的&安培;精心设计的代码。
让helperclass
返回null
以外的内容是部分模拟,因此他们不会喜欢它。