Unit test breaking after changing code base from SimpleMailMessage to MimeMessage

415 Views Asked by At

After executing the below test I am seeing following exception. All I changed in my code base was the usage of MimeMessage instead of SimpleMailMessage.

Please guide.

Exception

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.ebayenterprise.publicapi.events.webhooks.WebHookMailSenderServiceTest
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.548 sec <<< FAILURE! - in com.ebayenterprise.publicapi.events.webhooks.WebHookMailSenderServiceTest
sendNotification(com.ebayenterprise.publicapi.events.webhooks.WebHookMailSenderServiceTest)  Time elapsed: 1.159 sec  <<< FAILURE!
org.mockito.exceptions.verification.junit.ArgumentsAreDifferent: 
Argument(s) are different! Wanted:
mailSender.send(
    (hasProperty("from", "[email protected]"))
);
-> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
Actual invocation has different arguments:
mailSender.send(
    mimeMessage
);
-> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)

    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option UseSplitVerifier; support was removed in 8.0

Results :

Failed tests: 
  WebHookMailSenderServiceTest.sendNotification 
Argument(s) are different! Wanted:
mailSender.send(
    (hasProperty("from", "[email protected]"))
);
-> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
Actual invocation has different arguments:
mailSender.send(
    mimeMessage
);
-> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)


Tests run: 1, Failures: 1, Errors: 0, Skipped: 0

------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
Total time: 10.053 s
Finished at: 2017-09-05T15:24:11-04:00
Final Memory: 19M/318M
------------------------------------------------------------------------

WebHookMailSenderServiceTest.java

public class WebHookMailSenderServiceTest {

    @Rule
    public MockitoJUnitRule rule = new MockitoJUnitRule(this);
    private static final String EMAIL_SUBJECT = "Error Report For Webhooks Job Status";
    private static final String EMAIL_RECIPIENT_ADDRESS = "[email protected]";
    private static final String EMAIL_RECIPIENT_ADDRESSES = "[email protected],[email protected]";
    private static final String EMAIL_SENDER_ADDRESS = "[email protected]";
    private static final int SUCCESS_ROUTE_ID = 101;
    private static final int FAILURE_ROUTE_ID = 201;
    private static final String STORE_ID = "TMSUS";
    private static final String ENDPOINT = "http://tmsus-endpoint.com/pss";
    private static final String EVENT_TYPE = "PaymentSettlementStaus";
    private static final int MESSAGES_PROCESSED = 30;
    private static final String STATUS = "Success";
    private static final String ERROR_MESSAGE = "404 (Not Found)";
    private final Map<Integer, WebHookJobStatusCollector> successCollectorMap = new HashMap<>();
    private final Map<Integer, WebHookJobStatusCollector> failureCollectorMap = new HashMap<>();
    private WebHookMailSenderService webHookMailSenderService;
    private WebHookMailSenderService webHookMailSenderServiceWMultiRecipients;
    @Mock
    private JavaMailSender mailSender;
    @Mock
    private MimeMessage mimeMessage;

    @Before
    public void setup() {
        webHookMailSenderService = new WebHookMailSenderService(EMAIL_SENDER_ADDRESS, EMAIL_RECIPIENT_ADDRESS, mailSender);
        successCollectorMap.put(SUCCESS_ROUTE_ID, new WebHookJobStatusCollector(STORE_ID, ENDPOINT, EVENT_TYPE, MESSAGES_PROCESSED, STATUS, null));
        failureCollectorMap.put(FAILURE_ROUTE_ID, new WebHookJobStatusCollector(STORE_ID, ENDPOINT, EVENT_TYPE, MESSAGES_PROCESSED, STATUS, ERROR_MESSAGE));
    }

    @Test
    public void sendNotification() throws MessagingException {
        when(mailSender.createMimeMessage()).thenReturn(mimeMessage);
        webHookMailSenderService.sendNotification(successCollectorMap, failureCollectorMap);
        verify(mailSender).send((MimeMessage) argThat(allOf(
                hasProperty("from", equalTo(EMAIL_SENDER_ADDRESS))
        )));
    }

    @After
    public void cleanup() {
        webHookMailSenderService = null;
        assertNull(webHookMailSenderService);
    }
}

WebHookMailSenderService.java

public class WebHookMailSenderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebHookMailSenderService.class);
    private static final String EMAIL_SUBJECT = "Error Report For Webhooks Job Status";
    private String emailSenderAddress;
    private JavaMailSender mailSender;
    private String[] emailRecipientAddresses;
    private static final FastDateFormat EXECUTION_TIME_DATE_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss Z");
    private static final String VELOCITY_TEMPLATE_NAME = "webhooksjobstatus-error-summary.vm";
    private static final boolean HTML_FLAG = true;

    public WebHookMailSenderService() {
    }

    public WebHookMailSenderService(String emailSenderAddress, String emailRecipientAddresses, JavaMailSender mailSender) {
        this.emailSenderAddress = emailSenderAddress;
        this.emailRecipientAddresses = StringUtils.split(emailRecipientAddresses, ',');
        this.mailSender = mailSender;
    }

    public void sendNotification(Map<Integer, WebHookJobStatusCollector> successCollectorMap,
            Map<Integer, WebHookJobStatusCollector> failureCollectorMap) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message);
        helper.setSubject(EMAIL_SUBJECT + " on " + GenericUtil.getHostName());
        helper.setFrom(emailSenderAddress);
        helper.setTo(emailRecipientAddresses);
        String emailContent = getEmailContent2(successCollectorMap, failureCollectorMap);
        helper.setText(emailContent, HTML_FLAG);
        mailSender.send(message);
    }

    //code removed for brevity
}
1

There are 1 best solutions below

0
On

In your test you provide a mocked message:

@Mock
private MimeMessage mimeMessage;

when(mailSender.createMimeMessage()).thenReturn(mimeMessage);

which is in the production code will be populated for example like:

helper.setFrom(emailSenderAddress);

But nothing happened because production code works with mocked instance which ignores all setXXX() calls.

As result the send() call works with still empty mocked message:

mailSender.send(message);

Try in your test work with some stub of MimeMessage:

when(mailSender.createMimeMessage()).thenReturn(new MimeMessage(mockedSession));

In this case MimeMessageHelper will set data to real instance, not mocked one.