Mocking javax.mail.Transport
Asked Answered
R

9

6

Without creating another class that I can inject. Is it possible to mock javax.mail.Transport so I can do some mock testing of the Transport.send() method on Java EE 7?

Riding answered 3/7, 2013 at 20:18 Comment(0)
R
7

Following up on Bill Shanon's solution since Dumbster does not have a currently working Maven Central artifact, I used GreenMail.

Then I used the following code:

final GreenMail mailServer = new GreenMail();
mailServer.start();

final Properties mailSessionProperties = new Properties();
mailSessionProperties.put("mail.smtp.port", String.valueOf(mailServer.getSmtp().getPort()));

final javax.mail.Session mailSession = javax.mail.Session.getInstance(mailSessionProperties);

testObject.setMailSession(mailSession);

That way testObject does not need to change even if it has a static call to Transport.send(message).

Riding answered 4/7, 2013 at 0:42 Comment(1)
The main advantage of using GreenMail is that your test can then verify that the expected email was sent. I've added in my tests things like this: MimeMessage[] messages = mailServer.getReceivedMessages(); assertEquals(1, messages.length, "Failed to receive registration email"); assertEquals(1, messages[0].getHeader("To").length, "Malformed To headers in received registration email"); assertEquals(user.getEmail(), messages[0].getHeader("To")[0]);Highness
A
2

If what you want is to not call Transport.send while testing then you could use this:

@RunWith(PowerMockRunner.class)
@PrepareForTest(javax.mail.Transport.class)
public class MyClassTest {
    @Before
    public void before() throws Exception {
        suppress(method(Transport.class, "send", Message.class));
    }
}

see also https://groups.google.com/forum/#!topic/powermock/r26PLsrcxyA

Affix answered 3/4, 2015 at 17:54 Comment(0)
Y
2

Another approach that hasn't been discussed is to wrap calls to Transport.send(message) in a class that delegates the call. It's a bit of overhead in your code base, but it allows you to mock your delegating class and create the outcomes you want.

public class TransportDelegator {
    public void send(Message msg) throws MessagingException {
        Transport.send(msg)
    }
}

Then mock TransportDelegator as you would in whatever framework you are using.

Yalu answered 20/10, 2017 at 3:53 Comment(0)
P
1

Yes. On way is to use Mockito. https://code.google.com/p/mockito/

public class CategoryDAOTest {

    private Transport transport = Mockito.mock(Transport.class);

    @Test
    public void sendMessage() throws MessagingException {
        transport.sendMessage(null, null);
    }
}

Or, using annotations to create the mock:

@RunWith(MockitoJUnitRunner.class)
public class CategoryDAOTest {

    @Mock
    private Transport transport;

    @Test
    public void sendMessage() throws MessagingException {
        transport.sendMessage(null, null);
    }
}  
Petasus answered 3/7, 2013 at 20:52 Comment(2)
unfortunately this is only on the test, but if "Transport" is used inside the implementation class, then it won't be testable.Riding
Inject your mock into the class that uses it, before testing that class-- which is actually the most common way to use mocks.Petasus
T
1

I created a new wrapper class and Mocked it with Mockito. This prevented me from adding PowerMock to my project.

public class MyTransport{
  public void send(MineMessage msg) throws MessagingException{
    javax.mail.Transport.send(msg);
  }
}

In side test class we just need

@Mock
private MyTransport myTransport

This will do nothing when is called. You may also want to verifiy myTransport is getting called.

Mockito.verify(myTransport).send(correctMsg);
Triangulate answered 28/1, 2019 at 13:6 Comment(0)
F
0

Another approach is to use a fake SMTP server such as Dumbster. The JUnit tests in the JavaMail source workspace use a similar approach.

Factotum answered 3/7, 2013 at 21:5 Comment(0)
M
0

You can try JavaMail Mock2 https://github.com/salyh/javamail-mock2

It primarily focused on IMAP/POP3 but SMTP Mock is also available. In your case the "Fullmock" mode is a good choice. Its also available in maven central.

Mcferren answered 3/5, 2014 at 7:26 Comment(0)
R
0

If you are on linux / osx you can use python to create a mock smtp server, like that:

python -m smtpd -n -c DebuggingServer localhost:1025

Then it is enough if you connect to port 1025 on localhost and you can send emails. The Python code can be started by simple ProcessBuilder call (How to run Unix shell script from Java code?).

Roos answered 2/12, 2014 at 14:45 Comment(0)
G
0

This is How I did after hours of research, I was sending a list of attachments paths along with email to my method. everything workd fine

@Test
public void testWhenMigrationReportSentSuccessfully() throws Exception {
    mockStatic(Transport.class);
    PowerMockito.doNothing().when(Transport.class, "send", any(Message.class));
    service.report(anyList(), "[email protected]");
}
Glottal answered 29/7, 2020 at 8:27 Comment(2)
what dependencies are needed for PowerMockito?Larch
PowerMockito is a buggy library, conflicts with the latest Mockito 4.Larch

© 2022 - 2024 — McMap. All rights reserved.