netajik
netajik

Reputation: 306

How to mock and write unit test for try and catch block using mockito

In below example i am trying to test both catch and try block using mockito. And also when the CustomException is raised then i want to call the method with second host. Thank you.

private static void getDetails()
{
    final String host1 = "http://localhost:8080/springrestexample/employee/id";
   
    final String host2 = "http://localhost:8080/springrestexample/student/id";

     
    RestTemplate restTemplate = new RestTemplate();
    String result = null;
    try {
        String result = restTemplate.getForObject(host1, String.class);
    } catch(CustomException customException) {
       String result = restTemplate.getForObject(host2, String.class);
    }
    return result;
}

Upvotes: 0

Views: 7482

Answers (2)

Ravinda Lakshan
Ravinda Lakshan

Reputation: 1104

Ok, First of all, your original method needs to be like below. (since normal practice is we don't test private methods and if you need a static method to be tested you need something more than Mockito (PowerMock))

public class Example {

    @Autowired
    public RestTemplate restTemplate;

    public  String restTemplateTest()
    {
        final String host1 = "http://localhost:8080/springrestexample/employee/id";

        final String host2 = "http://localhost:8080/springrestexample/student/id";

        String result;
        try {
             result = restTemplate.getForObject(host1, String.class);
        } catch(CustomException customException) {
             result = restTemplate.getForObject(host2, String.class);
        }
        return result;
    }
}

Below is the sample test for the above method.

    public class ExampleTest {
    
       @Mock
       private RestTemplate restTemplate;
    
       @InjectMocks
       private Example testExample;
    
       @BeforeEach
       public void setUp()
       {
           MockitoAnnotations.initMocks(this);
       }
    
        @Test
        public void restTemplateTest() {
    
            Mockito.when(restTemplate.getForObject(Mockito.eq("http://localhost:8080/springrestexample/employee/id"), Mockito.eq(String.class)))
                    .thenThrow(CustomException.class);
    
            Mockito.when(restTemplate.getForObject(Mockito.eq("http://localhost:8080/springrestexample/student/id"), Mockito.eq(String.class)))
                    .thenReturn("expected");
    
            testExample.restTemplateTest();
    
            // if exception thrown , then rest template mock will invoke 2 times, otherwise
            // 1
            Mockito.verify(restTemplate, Mockito.times(2)).getForObject(Mockito.anyString(), Mockito.eq(String.class));
    
        }

}

Below is the way to test when no Exception occurs scenario.

@Test
public void restTemplateTest_when_no_exception() {

    Mockito.when(restTemplate.getForObject(Mockito.eq("http://localhost:8080/springrestexample/employee/id"), Mockito.eq(String.class)))
            .thenReturn("expectedString");

    String actual = testExample.restTemplateTest();

    // if exception not thrown , then rest template mock will invoke 1 times, otherwise
    // 1
    Mockito.verify(restTemplate, Mockito.times(1)).getForObject(Mockito.anyString(), Mockito.eq(String.class));

    Assert.assertEquals("expectedString",actual);
}

Upvotes: 2

Sabareesh Muralidharan
Sabareesh Muralidharan

Reputation: 647

Would it be possible to have restTemplate being passed to that method as an arg.

(If yes, then)

Using org.mockito.Mockito -> mock() you can mock like below,

RestTemplate restTemplateMock = mock(RestTemplate.class);
when(restTemplateMock.getForObject(host1)).thenThrow(CustomException.class);

Pass this mock object to your method and it will throw exception inside try.

Update: Sample test cases for your ref.

@Test
public void testGetDetails()
{
  RestTemplate restTemplateMock = mock(RestTemplate.class);
  when(restTemplateMock.getForObject(host1)).thenReturn(SOME_STRING);
  String result = //call your method
  assertThat(result).isEqualTo(SOME_STRING);
}

@Test
public void testGetDetailsUsesOtherHostWhenExceptionIsThrown()
{
  RestTemplate restTemplateMock = mock(RestTemplate.class);
  when(restTemplateMock.getForObject(host1)).thenThrow(CustomException.class);
  when(restTemplateMock.getForObject(host2)).thenReturn(SOME_STRING);
  String result = //call your method
  assertThat(result).isEqualTo(SOME_STRING);
}

When you in need to use same mock object,

RestTemplate myRestTemplateMock = mock(RestTemplate.class);

@Test
public void testGetDetails()
{
  when(myRestTemplateMock.getForObject(host1)).thenReturn(SOME_STRING);
  String result = //call your method
  assertThat(result).isEqualTo(SOME_STRING);
}

@Test
public void testGetDetailsUsesOtherHostWhenExceptionIsThrown()
{ 
  
  when(myRestTemplateMock.getForObject(host1)).
                                  thenThrow(CustomException.class);
  when(myRestTemplateMock.getForObject(host2)).thenReturn(SOME_STRING);
  String result = //call your method
  assertThat(result).isEqualTo(SOME_STRING);
}

Upvotes: 2

Related Questions