Модульное тестирование внедрения зависимостей Java - PullRequest
0 голосов
/ 19 сентября 2019

Может ли кто-нибудь сделать тест джунита в этом классе?

public class MyApplication {
    private EmailService email = new EmailService();

    public boolean processMessages (String msg , String recipient ) {
        if (msg.length ==0 | | recipient.length ==0 ) {
            return false ;
        }
        return this.email.sendEmail (msg , recipient ) ;
    }
}

Ответы [ 3 ]

1 голос
/ 19 сентября 2019

Ваш заголовок проясняет проблему: вы не вводите зависимость от EmailService.Чтобы сделать это, добавьте сеттер или (лучше) сделайте его final и добавьте его в конструктор.

Это будет выглядеть так:

public class MyApplication {
    private final EmailService email;

    public MyApplication(EmailService email) {
        this.email = email;
    }

    public boolean processMessages (String msg , String recipient ) {
        if (msg.length == 0 || recipient.length == 0 ) {
            return false ;
        }
        return this.email.sendEmail (msg , recipient ) ;
    }
}

И соответствующий тест может быть(используя junit и mockito):

private MyApplication app;
private EmailService email;

@BeforeEach
void setup() {
    email = mock(EmailService.class);
    when(email.sendEmail(any(), any())).thenReturn(true);
    app = new MyApplication(email);
}

@Test
void testProcessZeroLengthMessageOrPerson() {
    assertFalse(app.processMessages("", "Person"));
    assertFalse(app.processMessages("Message", "")):
    assertFalse(app.processMessages("", "")):
}

@Test
void testProcessMessage() {
    assertTrue(app.processMessage("Message", "Person"));
    verify(email).sendEmail("Message", "Person");
}
0 голосов
/ 19 сентября 2019

Очевидным решением было бы вместо этого использовать внедрение зависимостей.Вы уже знакомы с этим термином, поэтому я предполагаю, что вы достаточно изобретательны, чтобы найти информацию, необходимую для применения инъекций зависимостей к классу под рукой (для этого есть информация по всему Интернету - Википедия, YouTube, этот сайти многое другое ..).

Однако, учитывая сценарий, в котором вы хотите протестировать этот класс и не хотите или не можете изменить его исходный код и исправить нарушение, тогда, если EmailService и EmailService#sendEmail не являются окончательными, вы можете использовать отражение:

@Test
public void testWithoutDependencyInjection() throws NoSuchFieldException, IllegalAccessException {
    Map<String, String> expected = new HashMap<>();
    expected.put("Dimitris Sourailidis", "Yes, you can! But you should use dependency injection instead.");
    Map<String, String> actual = new HashMap<>();

    MyApplication app = new MyApplication();
    Field emailField = MyApplication.class.getDeclaredField("email");
    emailField.setAccessible(true);
    emailField.set(app, new EmailService() {
        @Override
        public boolean sendEmail(String msg, String email) {
            actual.put(msg, email);
            return true;
        }
    });

    for (String recipient : expected.keySet()) {
        app.processMessages(recipient, expected.get(recipient));
    }

    assertEquals(expected, actual);
}

Если они являются окончательными, тогда мы можем создать новый ClassLoader, который будет переопределять EmailService нашим собственным классом (возможно, однажды я отредактирую)ответ на этот вопрос и пример этого).

Хотя эти методы позволяют тестировать классы-нарушители, они предназначены для тестов, которые трудно понять и поддерживать.Я дважды подумал, прежде чем добавить тест, подобный одному из вышеперечисленных, в свой набор тестов, и рассмотрю возможность рефакторинга или замены тестируемого класса задолго до этого.

0 голосов
/ 19 сентября 2019

Я выполнил тесты для почтовой службы, используя зеленую почту

@Autowired
@Qualifier("emailSenderService")
private SenderService service;

@Autowired
@Rule
public SmtpServerRule smtpServerRule;

@Test
public void send() throws IOException, MessagingException {

    final String CONTENT = Util.randomValue();

    Message message = create();

   /* ... */

    service.send(message);

    Assert.assertTrue(smtpServerRule.getMessages().stream().findFirst().isPresent());

    String messageContent = String.valueOf(smtpServerRule.getMessages().stream().findFirst().get().getContent()).trim();

    Assert.assertTrue(messageContent.equalsIgnoreCase(CONTENT));
}

github

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...