0

In a class that I am testing with PowerMock I have the following instantiation of a class

EmailMessage msg = new EmailMessage(getExchangeSession());

EmailMessage is a third party tool that I am mocking while getExchangeSession() is a enherited protected method. I need to mock the EmailMessage but I really don't care about the call to getExchangeSession().

At the moment I have the following, but the getExchangeSession() method is still called:

@RunWith(PowerMockRunner.class)
@PrepareForTest({EmailProvider.class, ExchangeService.class})
public class MyTest {

    @Test
    public void test() {
        EmailMessage emailMessage = createMock(EmailMessage.class);
        ExchangeService exchangeService = createMock(ExchangeService.class);
        expectNew(EmailMessage.class, exchangeService).andReturn(emailMessage);

        // test setup and call to the class under test
        Email email = new Email();
        new EmailProvider().send(email);
    }
}

public class EmailProvider() extends ClassWithProtectedAccess {
    public void send(Email email) {
        EmailMessage msg = new EmailMessage(getExchangeSession());

        // and here follows the code that I am actually testing
        // and which works on the msg (EmailMessage)
        // ...
    }
}

The first line of EmailProvider.send() is it that runs getExchangeSession() and which then fails.

So apparently I can't skip the call to getExchangeSession(), and I should probably mock this method also. Is this correct? And if so, using PowerMock with EasyMock how can I mock this protected method?

homaxto
  • 5,428
  • 8
  • 37
  • 53
  • 1
    Have you added these to your tests? @RunWith(PowerMockRunner.class) @PrepareForTest(Test.class). Also you can check out this link for use of powermock.expectprivate which may also work for protected methods (I use justmock myself so not 100% sure) EDIT(add link):http://stackoverflow.com/questions/17027582/powermock-easymock-private-void-method-without-invokation – Josh Jun 12 '13 at 14:19

2 Answers2

1

If the class you are testing has this line in it:

EmailMessage msg = new EmailMessage(getExchangeSession());

then you can't skip the call to getExchangeSession() by powermocking the constructor of EmailMessage - it's called before the constructor is invoked, and the return value is then passed to EmailMessage (regardless of whether that is real or mocked).

So, if you can't set up your class such that the call to getExchangeSession works, you will need to mock that call as described at this question: mocking protected method.

Community
  • 1
  • 1
Matthew Gilliard
  • 9,298
  • 3
  • 33
  • 48
0

As i understood your question correctly, your are expecting to mock EmailMessage class, but need to skip the constructor call when you create an instance.

    ... test setup and call to the class under test ...
    Email email = new Email();
    new EmailProvider().send(email);

The problem is the way you test. Your intention is to test the code in send method. you cannot just call that send() method to test. You need to write code a test the statements in send() method by mocking the dependency classes and test other statement in the class

public void testSend() throws Exception 
{
  // you need to suppress the constructor before you mock the class.
   PowerMockito.suppress(PowerMockito.constructor(EmailMessage.class));
   EmailMessage emailMessage = PowerMockito.mock(EmailMessage.class);
   Email email = new Email();
   emailMessage.setSubject(email.getSubject());
  // ...your other code here ...

}
Libin
  • 16,967
  • 7
  • 61
  • 83
  • Thank you for your answer. Unfortunately it did not change anything - the getExchangeSession() is still called. – homaxto Jun 13 '13 at 14:58
  • I have edited the answer . Please let me know your comments or your view if you think different – Libin Jun 13 '13 at 23:50
  • I don't want to call EmailMessage.setSubjet() in my code, since the method I need to test is EmailProvider.send() - which during it's processing calls the EmailMessage.setSubjet(). – homaxto Jun 14 '13 at 11:21