Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a javax.mail.Session

i need to mock a javax.mail.Session object in my unit tests. The class javax.mail.Session is marked final so Mockito is not able to create a mock. Does anyone have an idea how to fix this?

Edit: My test is an Arquillian test and has already an annotation @RunWith(Arquillian.class). Therefore powermock is not an option.

like image 744
martin Avatar asked Nov 21 '11 14:11

martin


3 Answers

Use PowerMockito to mock it.

@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(javax.mail.Session.class)
public class YourTestCase {

  @Test
  public void test() throws Exception {

    PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
  }
}
like image 132
Boris Pavlović Avatar answered Nov 04 '22 12:11

Boris Pavlović


You may refactor your code a little bit. In the "Working with Legacy Code" book by Martin Fowler, he describes a technique of separating the external API (think Java Mail API) from your own application code. The technique is called "Wrap and Skin" and is pretty simple.

What you should do is simply:

  1. Create an interface MySession (which is your own stuff) by extracting methods from the javax.mail.Session class.
  2. Implement that interface by creating a concrete class (looking a bit like the original javax.mail.Session)
  3. In each method DELEGATE the call to equivalent javax.mail.Session method
  4. Create your mock class which implements MySession :-)
  5. Update your production code to use MySession instead of javax.mail.Session

Happy testing!

EDIT: Also take a look at this blog post: http://www.mhaller.de/archives/18-How-to-mock-a-thirdparty-final-class.html

like image 10
nowaq Avatar answered Nov 04 '22 11:11

nowaq


You can use the Mock JavaMail project. I first found it from Kohsuke Kawaguchi. Alan Franzoni also has a primer for it on his blog.

When you put this jar file in your classpath, it substitutes any sending of mail to in memory mailboxes that can be checked immediately. It's super easy to use.

Adding this to your classpath is admittedly a pretty heavy handed way to mock something, but you rarely want to send real emails in your automated tests anyway.

like image 5
jhericks Avatar answered Nov 04 '22 10:11

jhericks