-1

I know there is an indirect answer to that question in other posts here on stackoverflow. For example this:

link

But I would need the most simple and direct answer to my particular question. Since one thing is still not entirely clear to me. I will give details below.

I am going to use an example from a book of Tomasz Kaczanowski - "Practical Unit testing with JUnit and Mockito"

The example is as follows:

Class to be tested:

public class Messenger {

    private TemplateEngine templateEngine;

    private MailServer mailServer;

    public Messenger(MailServer mailServer, TemplateEngine templateEngine) {
        this.mailServer = mailServer;
        this.templateEngine = templateEngine;
    }

    public void sendMessage(Client client, Template template) {

        String msgContent = templateEngine.prepareMessage(template, client);

        mailServer.send(client.getEmail(), msgContent);
    }
}

Test class:

public class MessengerTest {

    private static final String CLIENT_EMAIL = "some@email.com";
    private static final String MSG_CONTENT = "Dear John! You are fired.";

    @Test
    public void shouldSendEmail() {

    Template template = mock(Template.class);
    Client client = mock(Client.class);
    MailServer mailServer = mock(MailServer.class);
    TemplateEngine templateEngine = mock(TemplateEngine.class);

    Messenger sut = new Messenger(mailServer, templateEngine);

    when(client.getEmail()).thenReturn(CLIENT_EMAIL);
    when(templateEngine.prepareMessage(template, client)).thenReturn(MSG_CONTENT);

    sut.sendMessage(client, template);

    verify(mailServer).send(CLIENT_EMAIL, MSG_CONTENT);
    }
}

(I tried to format the code and make the sytnax highlited, but I don't know how to do it, even though I read some posts on meta.stackoverflow. Would appreciate hints on that as well.)

So my question is: Is the code below with annotations equivalent?

public class MessengerTest {

    private static final String CLIENT_EMAIL = "some@email.com";
    private static final String MSG_CONTENT = "Dear John! You are fired.";

    @Test
    public void shouldSendEmail() {

    @Mock
    Template template;

    @Mock
    Client client;

    @Mock
    MailServer mailServer;

    @Mock
    TemplateEngine templateEngine;

    @InjectMocks
    Messenger sut;

    // given
    when(client.getEmail()).thenReturn(CLIENT_EMAIL);
    when(templateEngine.prepareMessage(template, client)).thenReturn(MSG_CONTENT);

    // when
    sut.sendMessage(client, template);

    // then
    verify(mailServer).send(CLIENT_EMAIL, MSG_CONTENT);
    }
}

Are the comments

// given 
// when 
// then 

used properly, as good practice says?

Also, in the mentioned similar question it says, that if I want to use annotations, I need to annotate my test class with: @RunWith(MockitoJUnitRunner.class)

So it is done in the question mentioned. But in my production code I am reading, there is no such annotation, and the tests work. How come? Is that annotation necessary, or not?

Community
  • 1
  • 1
so_user
  • 333
  • 3
  • 15

1 Answers1

1

The comments are well placed, but the code is wrong, I don't even think it compiles. This code would work :

@RunWith(MockitoJUnitRunner.class)
public class MessengerTest {

    private static final String CLIENT_EMAIL = "some@email.com";
    private static final String MSG_CONTENT = "Dear John! You are fired.";

    @Mock Template template;
    @Mock Client client;
    @Mock MailServer mailServer;
    @Mock TemplateEngine templateEngine;

    @InjectMocks Messenger sut;

    @Test
    public void shouldSendEmail() {
        // given
        when(client.getEmail()).thenReturn(CLIENT_EMAIL);
        when(templateEngine.prepareMessage(template, client)).thenReturn(MSG_CONTENT);

        // when
        sut.sendMessage(client, template);

        // then
        verify(mailServer).send(CLIENT_EMAIL, MSG_CONTENT);
    }
}

Don't forget the the runner (as shown in the above snippet), or a mockito rule (available only in the latests releases).

Also, in the mentioned similar question it says, that if I want to use annotations, I need to annotate my test class with: @RunWith(MockitoJUnitRunner.class)

Another possibility to make the test work is to have an test init method like that :

@Before public void init_mocks() { MockitoAnnotations.initMocks(this); }
bric3
  • 40,072
  • 9
  • 91
  • 111
  • Thank you! That was helpful! Also can you tell me how did you edit my code, so it got properly highlighted? I have read this post: http://meta.stackexchange.com/questions/184108/what-is-syntax-highlighting-and-how-does-it-work, but still didn't help much. – so_user Dec 19 '14 at 11:08
  • I removed the 'mocking' tag, since it's not really useful in the question, there's already a `mockito` tag, and I used the java tag, SO handles understand this tag and will prettify the code accordingly. There are other ways documented in the [help](http://stackoverflow.com/editing-help#syntax-highlighting). – bric3 Dec 19 '14 at 14:28