模拟Java中的匿名类

时间:2019-06-17 15:52:04

标签: java junit dependency-injection mockito

我正在学习有关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;
    }

} 

第二个问题是关于在没有依赖注入的情况下测试应用程序。我不明白他为什么这么说:“测试应用程序将非常困难,因为我们的应用程序直接创建了电子邮件服务实例。我们无法在测试类中模拟这些对象。”为什么我们不能在测试用例中模拟这些对象。

1 个答案:

答案 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);
    }
}