How to test one method that depends on the result of another with Junit?

Asked

Viewed 666 times

1

Greetings,

I have a class that does actions in an email. I created some tests for this class and would like to know if this is a valid form of testing or if there is any better way to do it.

I test the reading of emails and then test move messages from one folder to another, but the messages that will be moved depend on the reading. Therefore I need to call the read method inside the drive method as well so that I can move at least one message. Ideally Mock the Message Array?

I am perfecting my studies in tests yet, so feel free to criticism and suggestions

Below is the test class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@ActiveProfiles("teste")
public class EmailTest {

    ReadEmail readEmail = new ReadEmail();
    MoveMessages moveMessages = new MoveMessages();

    private static final Logger LOGGER = LoggerFactory.getLogger(EmailTest.class.getSimpleName());

    @Test
    public void readEmail() {
        Message[] messages = new Message[0];

        ReflectionTestUtils.setField(readEmail, "usuario", "usuario");
        ReflectionTestUtils.setField(readEmail, "senha", "senha");
        ReflectionTestUtils.setField(readEmail, "host", "host");

        try {
            messages = readEmail.read();
        } catch (EmailException e) {
            Assert.assertTrue(e.getMessage().contains("!! ERRO AO CAPTURAR AS MENSAGENS"));
        }

        assert Objects.nonNull(messages);
        Assert.assertTrue(messages.length > 0);
        Assert.assertTrue(Arrays.stream(messages).anyMatch(message -> {
            try {
                return InternetAddress.toString(message.getFrom()).contains("@domain.com.br");
            } catch (MessagingException e) {
                LOGGER.error("Erro ao buscar remetente");
            }
            return false;
        }));
    }

    @Test
    public void moveEmail() {

        Message[] messages = new Message[0];

        ReflectionTestUtils.setField(readEmail, "usuario", "usuario");
        ReflectionTestUtils.setField(readEmail, "senha", "senha");
        ReflectionTestUtils.setField(readEmail, "host", "host");

        try {
            messages = readEmail.read();
        } catch (EmailException e) {
            LOGGER.error("Erro ao capturar mensagens para serem movidas: {}", e.getMessage());
        }

        assert Objects.nonNull(messages);
        assert messages.length > 0;

        Message[] messagesParam = new Message[1];
        messagesParam[0] = messages[0];

        try {
            moveMessages.move("Inbox", "teste", messagesParam);
        } catch (EmailException e) {
            Assert.assertTrue(e.getMessage().contains("!! ERRO AO MOVER AS MENSAGENS"));
        }

        // ASSERTS ...
    }


}

Thank you.

  • You have the following test contexts: 1) Test read 2) Test move 3) Test both integrally. To test the move, you don’t need to read the messages, just provide a mock of messagesParam and perform the necessary checks on the mocks. To read the same thing. Now for the integrated test, you should read and move in the same test, not in separate tests

  • But if I mock the data on read how do I know if the search really works? I’m bringing my email messages. And on move the same thing. All right, I can even mock a real message from my email in that case, but if one day I delete that message for example, my test crashes because it will no longer locate the message in the email to move it.

  • Here’s the thing, it only makes sense for you to provide a mock if you’re performing unit tests to check just the read and only the move. For the integrated test you should provide a message in the box to be read, then carry out the move in the same test, without mock any

  • So it doesn’t make any sense for me to test the method read if you think about it. Because it just goes to the email box and brings all the messages from a particular sender. My test is based on seeing if it actually brings these messages. If I’m going to mock the messages, there’s nothing to test for this method. Correct?

  • What’s in the classes ReadEmail and MoveMessages?

  • The classes are large, but the ReadEmail searches for unread emails from an email filtering by a specific sender. The class MoveMessages moves emails read and filtered by ReadEmail to a different folder. You need the codes ?

  • 1

    Then spring has notes for you to create mocks and simulate the behavior This is the documentation of the Spring Mocks. <- There are examples of use. D

  • 1

    The idea of unitary testing is to test one thing only: if everything else works, does that particular stretch also work? To simulate "everything else working", mocks are used. If testing only the read, just check if the return has the correct messages. If you are testing only the move, the read is part of "all the rest", so he must be mockery (then you can create several scenarios: a list with multiple messages, an empty list, etc.). If you want to test two features (read + move) working together, it is no longer a unit test: https://stackoverflow.com/a/2741845

  • @Yurizamboni @hkotsubo Perfect, I understood that the ideal is to mock the messages. But imagine that I mock a message to the move move it. If this message does not exist in the email, it will return error, right?? My method move depends on the valid messages that my read brings. So I couldn’t leave this test in the code. I don’t know if you can understand the scenario I’m imagining.

  • Well, the unit test should not read the emails of an "official"/real/production box (just as a unit test should not access the bank, nor call services in real Urls on other machines, etc.), it should run in isolation, without external dependencies. You should have a box mockery (that behaves as if it were real), then you can manipulate it at will, without needing there to be emails in the real Inbox. So you do not depend on external factors and can still create various scenarios (empty Inbox, with multiple emails, etc). If you want to test with real emails, it’s no longer Unit test...

  • @hkotsubo I understand. Mt thank you !

Show 6 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.