我正在学习依赖注入和使用Mockito进行测试。我刚刚找到了一个教程,有人解释了一个有依赖注入和没有依赖注入的应用程序。这是链接:https://www.journaldev.com/2394/java-dependency-injection-design-pattern-example-tutorial
我有两个问题:
第一个问题是关于他为测试编写的代码。那是什么嘲讽?你不需要用@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;
}
}
第二个问题是关于在没有依赖注入的情况下测试应用程序。我不明白他为什么这么说:"测试应用程序将非常困难,因为我们的应用程序直接创建电子邮件服务实例。我们无法在测试类中模拟这些对象。为什么我们不能在测试用例中模拟这些对象。
第一个问题是关于他为测试编写的代码。那是什么嘲讽?你不需要用@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);
}
}