Hot questions for Using Mockito in exception handling

Top 10 Java Open Source / Mockito / exception handling

Question:

I have a simple Java method, I would like to check that it does not throw any exceptions.

I have already mocked the parameters etc, however I am not sure how to use Mockito to test that no exception has been thrown from the method?

Current test code:

  @Test
  public void testGetBalanceForPerson() {

   //creating mock person
   Person person1 = mock(Person.class);
   when(person1.getId()).thenReturn("mockedId");

  //calling method under test
  myClass.getBalanceForPerson(person1);

  //How to check that an exception isn't thrown?


}

Answer:

Fail the test if an exception is caught.

@Test
public void testGetBalanceForPerson() {

   // creating mock person
   Person person1 = mock(Person.class);
   when(person1.getId()).thenReturn("mockedId");

   // calling method under test
   try {
      myClass.getBalanceForPerson(person1);
   } catch(Exception e) {
      fail("Should not have thrown any exception");
   }
}

Question:

I'm writing unit test for legacy Java code. Now I'm encountering a problem. Below is the class A I want to write test code for.

class A {

    public A(){

    }

    public void doSomething()throws DBException {
        try{
            //some code that might throw JDBCConnectionException 
        }catch(JDBCConnectionException e){
            notifyJDBCConnection()
        }catch(Exception e){

        }
    }   

    private void notifyJDBCConnection(){
        //do notification stuff
    }
}

Now say if I need to test whether the method notifyJDBCConnection() has been executed when JDBCConnectionException is caught. What is the right way to approach this problem? Or should I just write a test for testing method notifyJDBCConnection is okay?


Answer:

I presume that notifyJDBCConnection will call some kind of notification framework, be it an email sender or otherwise. If you mock that component using a framework like Mockito, you can verify that the appropriate calls to said component have been made.

Question:

I'm trying to test the method below with Mockito and Junit:

@Transactional
@RequestMapping(method=RequestMethod.PUT,value ="/updateEmployer/{empId}")
public @ResponseBody Object updateEmployer(@PathVariable Integer empId,) throws Exception {

    Employee e = EmployeeRepository.findOne(empId);

    for (Department de : e.getDepartement()){
        de.setDepartmentName(e.getName + "_" + de.getName());       
    }
    EmployeeRepository..saveAndFlush(e);
    return null;
}   

This is the method Test:

@Test  // throw java.lang.NullPointerException
 public void updateEmployeeFailureTest() throws Exception {

        mockMvc.perform(
            MockMvcRequestBuilders
                    .put("/updateEmployer/{empId}",18)                      
                    .accept(MediaType.APPLICATION_JSON)).andDo(print())         

              .andExpect(MockMvcResultMatchers.view().name("errorPage"))
               .andExpect(MockMvcResultMatchers.model().attributeExists("exception"))
              .andExpect(MockMvcResultMatchers.forwardedUrl("/WEB-INF/jsp/errorPage.jsp"))
              .andExpect(MockMvcResultMatchers.status().isInternalServerError());       

    }   

The printstack:

 MockHttpServletRequest:
     HTTP Method = PUT
     Request URI = /updateEmployer/18
      Parameters = {}
         Headers = {Content-Type=[application/json], Accept=   application/json]}

         Handler:
            Type = com.controllers.employeeController
          Method = public java.lang.Object    com.controllers.employeeController.updateEmployer(java.lang.Integer) throws   java.lang.Exception

           Async:
      Was async started = false
      Async result = null

    Resolved Exception:
            ***Type = java.lang.NullPointerException***

    ModelAndView:
       View name = errorPage
            View = null
       Attribute = exception
           ***value = java.lang.NullPointerException***

         FlashMap:

  MockHttpServletResponse:
          Status = 500
   Error message = null
         Headers = {}
    Content type = null
            Body = 
   Forwarded URL = /WEB-INF/jsp/errorPage.jsp
  Redirected URL = null
         Cookies = []

It's work but when i try to catch the text or the exception throwed by this method adding @Test (expected= java.lang.NullPointerException.class) i have this error:

java.lang.AssertionError: Expected exception: java.lang.NullPointerException

when i try to get the nullPointerException Text as a value of the attribute (exception) of the section ModelAndView i get this error:

java.lang.AssertionError: Model attribute 'exception' expected:java.lang.NullPointerException but was:java.lang.NullPointerException

Is there a way to expect the exception throwed or the text in the value attribut ( value = java.lang.NullPointerException) or the Text in the Resolved Exception section using mockito (mockmvc)?

Any help will be much appreciated


Answer:

You need to test that the exception attribute of the model is an instance of NullPointerException.

This can be done using a Hamcrest matcher:

 .andExpect(MockMvcResultMatchers.model().attribute(
     "exception", 
      Matchers.isA(NullPointerException.class))

Question:

I am testing a method with an expected exception. I also need to verify that some code was called (on a mocked object) after the exception is thrown, but verification is being ignored. Here is the code:

public class ExceptionHandler {

    @Autowired
    private Sender sender;

    public void handle(Exception exception) throws Exception {
      if (!SomeException.class.isAssignableFrom(exception.getClass())) {
        sender.sendMessage(ExceptionUtils.getStackTrace(exception));
      }
      throw exception;
    }
}

Here is the test code:

@Mock
private Sender sender;

@InjectMocks
private ExceptionHandler handler;

@Test
public void testHandler() throws Exception {
    SomeException someException = new SomeException();

    try {
        handler.handle(someException);
    } catch (SomeException thrownResult) {
        assertEquals(someException, thrownResult);
    }

    verify(sender, times(1)).sendMessage(Mockito.anyString());
}

Answer:

I also need to verify that some code was called (on a mocked object) after the exception is thrown, but verification is being ignored.

This is not true, this line is actually executed:

verify(sender, times(1)).sendMessage(Mockito.anyString());

But it fails verification with this error:

Wanted but not invoked: sender.sendMessage();

<...>

Actually, there were zero interactions with this mock.

As expected, that method was never invoked, because condition !SomeException.class.isAssignableFrom(exception.getClass()) was not satisfied - you invoke handler.handle with instance of SomeException.

Question:

I want to write unit-test to check work of log.error function when exception is catched. I have this class:

class SalesMasterModelDateSequenceWrapper {

public static List<EMDate> getDatesClass(IAnalysisExpressionContext context, IContract contract, EMDate analysisDate, IExpressionLogger log, Lookup lookup) {

    try {

        StringBuilder scenarioName = new StringBuilder();
        scenarioName.append(contract.getStringFDA(lookup.getServerFDA("NewContractsForecastName").toLowerCase()));
        if (scenarioName.toString().length()==0) return new ArrayList<>();
        scenarioName.append("_").append(analysisDate.year()).append(analysisDate.month()).append(analysisDate.day());
        if (!context.getScenarioName().contains(scenarioName.toString())){
            return Arrays.asList(contract.getValueDate());
        }
    }
    catch (Exception e) {
        StringBuilder sb = new StringBuilder();
        sb.append("SalesMasterModelDateSequence: ").append(e.getMessage()).append("\n");
        for (StackTraceElement stackTraceElement : e.getStackTrace())
        {
            sb.append(stackTraceElement.toString()).append("\n");
        }
        log.error(sb.toString());
    }
    return new ArrayList<>();

}

I want to verify that I'll take the result of log.error(sb.toString()). Can somebody help with this issue? Thanks in advance.


Answer:

Unse a mocking framework to create a mock of IExpressionLogger and in your test verify that its error() method has been called with the expected parameter:

@Rule 
public MockitoRule mockitoRule = MockitoJUnit.rule(); 
@Mock
private IExpressionLogger expressionLogger;
@Mock
private Lookup lookup;
@Test
public void exceptionMessageLoggedAsError() {
 doThrow(new RuntimeException("UnitTest").when(lookup).getServerFDA(anyString());

  new SalesMasterModelDateSequenceWrapper(/* other parameters */,expressionLogger, lookup).getDatesClass(/* parameters */);

  verify(expressionLogger).error("the expected message containing substring 'UnitTest' from Exception");

}