我正在学习有关Mockito的可靠注入和测试的知识。我刚刚找到了一个教程,其中有人解释了具有依赖项注入和没有依赖项注入的应用程序。这是链接:https://www.journaldev.com/2394/java-dependency-injection-design-pattern-example-tutorial
我有2个问题:
第一个问题是关于他为测试编写的代码。那是什么样的模拟?您不需要使用@Mock模拟对象吗?
这是他的测试代码:
public class MyDIApplicationJUnitTest {
private MessageServiceInjector injector;
@Before
public void setUp(){
//mock the injector with anonymous class
injector = new MessageServiceInjector() {
@Override
public Consumer getConsumer() {
//mock the message service
return new MyDIApplication(new MessageService() {
@Override
public void sendMessage(String msg, String rec) {
System.out.println("Mock Message Service implementation");
}
});
}
};
}
@Test
public void test() {
Consumer consumer = injector.getConsumer();
consumer.processMessages("Hi Pankaj", "pankaj@abc.com");
}
@After
public void tear(){
injector = null;
}
}
第二个问题是关于在没有依赖注入的情况下测试应用程序。我不明白他为什么这么说:“测试应用程序将非常困难,因为我们的应用程序直接创建了电子邮件服务实例。我们无法在测试类中模拟这些对象。”为什么我们不能在测试用例中模拟这些对象。
答案 0 :(得分:2)
第一个问题是关于他为测试编写的代码。那是什么样的模拟?您不需要使用@Mock模拟对象吗?
要模拟对象,您必须提供具有相同类型的对象,即,其行为相同或是您要模拟的对象的类的子类型。因此,要模拟对象,您可以使用匿名类的实例(在您的情况下,它将是扩展MyDIApplication
的匿名类的对象),也可以将Mockito与其@Mock
注释一起使用,该注释基本上类似于事情。基本上使用@Mock
注释类似于:
MyDIApplication myDiApplication = Mockito.mock(MyDIApplication.class)
创建一个模拟对象扩展类,该类在构造函数中传递。在这里,您可以根据要模拟的内容传递接口或类。
使用匿名类时,您提供要在替代的方法实现中模拟的方法的实现,但是在Mockito的情况下,您可以使用Mockito::when
之类的方法来提供预期行为。
第二个问题是关于在没有依赖注入的情况下测试应用程序。我不明白他为什么这么说:“测试应用程序将非常困难,因为我们的应用程序直接创建了电子邮件服务实例。我们无法在测试类中模拟这些对象。”为什么我们不能在测试用例中模拟这些对象。
我猜您正在引用这段代码:
public class MyApplication {
private EmailService email = new EmailService();
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}
在这里创建EmailService
的实例作为类字段。因此,您不可能嘲笑它(尽管您可以使用反射或PowerMock)。因此,您与EmailService
紧密相连,因此很难测试MyApplication
类逻辑。要进行测试,可以使用构造函数注入:
public class MyApplication {
private EmailService email;
public MyApplication(EmailService emaliService) {
this.email = emailService;
}
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}
或二传手注射:
public class MyApplication {
private EmailService email;
public void setEmailService(EmailService emailService) {
this.email = emailService;
}
public void processMessages(String msg, String rec){
//do some msg validation, manipulation logic etc
this.email.sendEmail(msg, rec);
}
}