Насмешка над анонимным классом в Java - PullRequest
3 голосов
/ 17 июня 2019

Я учусь внедрению зависимостей и тестированию с помощью 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 Ответ

2 голосов
/ 17 июня 2019

Первый вопрос касается кода, который он пишет для тестирования. Что это за насмешка? Вам не нужно использовать @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);
    }
}
...