我正在为一个大量使用依赖注入的项目编写测试。
通常我只会注入我正在测试的对象:
public class RegistrationTest
extends WithApplication {
private RegistrationController controller;
@Before
public void setUp() throws Exception {
Injector injector = app.injector();
controller = injector.instanceOf(RegistrationController.class);
}
@Test
public void openRegistrationView() {
Result result = controller.registrationForm();
assertEquals(OK, result.status());
}
}
现在我需要模拟一个被测试类的依赖关系的方法的返回值。
为此,我可以使用@InjectMocks
和@RunWith(MockitoJUnitRunner.class)
注入模拟的依赖项。
@RunWith(MockitoJUnitRunner.class)
public class RegistrationTest
extends WithApplication {
@InjectMocks
private RegistrationController controller;
@Mock
private FormFactory formFactory;
@Mock
private RegistrationIpCache registrationIpCache;
@Test
public void openRegistrationView() {
doReturn("test").when(registrationIpCache).getLast();
Result result = controller.registrationForm();
assertEquals(OK, result.status());
}
}
但是我只想模拟RegistrationIpCache
的一个方法调用,我需要模拟整个类,并且我需要在我的示例中模拟RegistrationController
的所有其他依赖项,如FormFactory
。现在,所有模拟类的每个方法都没有按预期工作。
当然,我可以使用doCallRealMethod()
来模拟所有依赖项的每个方法
doCallRealMethod().when(formFactory).form(Registration.class);
但正如您已经可以想象的那样,工作所需的样板代码量是极端的。
是否可以正常注入我的课程,然后只监视一个依赖项或模拟一个依赖项的一个方法?
答案 0 :(得分:3)
您需要使用@Spy
而不是@Mock
。
@InjectMocks
private RegistrationController controller;
@Mock
private FormFactory formFactory;
@Spy
private RegistrationIpCache registrationIpCache;
但请注意,在这种情况下@Spy
将尝试使用默认构造函数。
如果默认构造函数不可用,请使用显式构造函数调用:
@Spy
private RegistrationIpCache registrationIpCache = new RegistrationIpCache(dependencies);
以下是Mockito无法从@Spy
javadoc实例化您的课程的情况:
Mockito将尝试找到零参数构造函数(甚至私有)和 为你创建一个实例。但是Mockito无法实例化内心 类,本地类,抽象类和接口。
以下是手动注入依赖项的示例:
@RunWith(MockitoJUnitRunner.class)
public class RegistrationTest {
private RegistrationController controller;
private RegistrationIpCache spyRegistrationIpCache; //this is the dependencies that you need to spy
@Before
public void setUp() throws Exception {
spyRegistrationIpCache = spy(realInstanceOfregistrationIpCache);
controller = new RegistrationController(registrationIpCache, realInstanceOfFormFactory);
}
}
在这种情况下,您需要编写更多代码,但这使您可以更好地控制对象实例化和依赖项注入。 请注意,不需要使用构造函数实例化。由于您手动执行此操作,因此可以根据需要对其进行实例化。