15

I'm using Mockito for my unit tests and I encounetered a problem with throwing exception on spied object. I have done this before on this object (in different test case and it worked). Here's the test code:

@Test
public void callInitiated_FsmInitializationException() throws FsmInitializationException, Exception {
    MocSbb moc = Mockito.spy(testObj);

    MocTracer tracer = Mockito.mock(MocTracer.class);
    Mockito.doReturn(tracer).when(moc).getTracer();

    CAP2InitialDPArg idp = Mockito.mock(CAP2InitialDPArg.class);
    MocFsm mocFsm = Mockito.mock(MocFsm.class);
    //Mockito.doReturn(mocFsm).when(moc).getSs7Fsm();

    TicketingLocalInterface ticketing = mockTicketingLocalInterface();
    CAP2InitialDPArgWrap idpWrap = Mockito.mock(CAP2InitialDPArgWrap.class);
    PowerMockito.whenNew(CAP2InitialDPArgWrap.class).withArguments(idp, tracer).thenReturn(idpWrap);

    MocSession mocSession = Mockito.mock(MocSession.class);
    Mockito.doReturn(mocSession).when(moc).getMocSession();

    Mockito.when(moc.getSs7Fsm()).thenThrow(new FsmInitializationException()); ////HERE'S THE PROBLEM

    moc.callInitiated(idp);

    verify(moc).getFailedFsm();
} 

here's the method on which the exception should be thrown:

protected MocFsm getSs7Fsm() throws FsmInitializationException {
    mocFsm.setContextProvider(getMocLocalObject());
    return mocFsm;
}  

the error I get during test execution looks like this:

Testcase: callInitiated_FsmInitializationException(com.nsn.as.ccs.moc.sbb.MocSbbTest):  Caused an ERROR

Checked exception is invalid for this method!
Invalid: com.nsn.as.ccs.moc.fsm.FsmInitializationException
org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: com.nsn.as.ccs.moc.fsm.FsmInitializationException
at com.nsn.as.ccs.moc.sbb.MocSbbTest.callInitiated_FsmInitializationException(MocSbbTest.java:1194)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:322)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:309)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:297)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:222)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:161)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:133)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:112)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)  

Does anyone have any idea why it doesn't work in this case?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Edheene
  • 455
  • 2
  • 7
  • 20
  • 1
    Not a duplicate but another question on that topic: http://stackoverflow.com/questions/3762047/throw-checked-exceptions-from-mocks-with-mockito – Andreas Dolk Jul 11 '11 at 09:31
  • I have seen that, but it doesn't answer my question. thanks though – Edheene Jul 11 '11 at 09:34
  • What is the type of testObj? Is it `MocSbb` or is it a super class or interface? Does the interface/parent class declare the exception also? –  Jul 11 '11 at 09:35

5 Answers5

10

I have finally found the solution for this problem.

We have used an anonymous class extending original Sbb class which was tested and in this extended class implementation of mentioned method was altered and throws expression was removed which caused the problem.

I should have read my colleagues code more carefully.

Ian Ringrose
  • 51,220
  • 55
  • 213
  • 317
Edheene
  • 455
  • 2
  • 7
  • 20
5

Following this answer. Using Mockito's doAnswer instead of thenThrow method solved my issue.

Mockito.doAnswer(
      invocation -> {
        throw new Exception("Something went wrong");
      })
  .when(moc)
  .getSs7Fsm();

I know it's too late but just in case anyone faces the same issue.

Mohamed Nageh
  • 1,963
  • 1
  • 19
  • 27
4

I have a feeling the solution is to use doThrow() syntax instead of when().thenThrow(). When spying it is safer to use doThrow/doReturn syntax for stubbing. The reasons are somewhat described in the documentation: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#13

I think we can improve an exception message in this instance so that it is m

Szczepan
  • 318
  • 2
  • 9
  • Reason: Stubbing voids requires different approach from Mockito.when(Object) because the compiler does not like void methods inside brackets... – rohanagarwal Aug 11 '17 at 13:26
  • This did not work for me. What ended up working was actually changing the exception to a RuntimeException type. It's not clear to me why Mockito doesn't allow checked exceptions to be thrown with these methods. – mjuarez Jan 11 '19 at 00:49
0

I know this post is very old but my solution it could be of help to someone: I solved this same error by changing the visibility of my method to be test to public.

In this case you whould have change

protected MocFsm getSs7Fsm() throws FsmInitializationException {
    ...
}

to

public MocFsm getSs7Fsm() throws FsmInitializationException {
    ...
}
Rubén Viguera
  • 3,277
  • 1
  • 17
  • 31
0

In my case, since I was using @SneakyThrows on my void method, I had to throw a RuntimeException, instead of a normal exception, in my mock, so

doThrow(new RuntimeException()).when(mock).doStuff(any());
mr nooby noob
  • 1,860
  • 5
  • 33
  • 56