0
votes

I have a class with the following method for which I want to write unit test:

public class Service {
    ..
    ..
    Test getTestObj(@NotNull Product product) {
        String prodJSON;
        try {
            prodJSON = Test.mapper.writeValueAsString(product);   // The class Test is defined as below and has the ObjectMapper property
            logger.info("product json", productJSON);
        } catch (JsonProcessingException e) {
            logger.error("...", e);
            ..
            throw new InternalServerErrorException("An error occured");
        }
        ...
        ...
    }
    ..
    ..
}


Test.java

public class Test {

    public static final ObjectMapper mapper = new ObjectMapper();
    ..
    ..
}   

Lets say, I have a Test class (ServiceTest.java) for Service.java, where I want to write a unit test for the method Test getTestObj(@NotNull Product product) { In this unit test, I basically want to cover the scenario where JsonProcessingException is thrown. So, I want to be able test the code:

} catch (JsonProcessingException e) {
            logger.error("...", e);
            throw new InternalServerErrorException("An error occured");
}

Lets say I start with my ServiceTest.java

@Test
public void getTestObjTest() {
    Product prod = new Productt();
    service.getTestObj(prod);
}

The above test will just cover the happy path where JsonProcessingException is not thrown. How can I modify my test so the JsonProcessingException gets thrown when invoking getTestObj?

Please note that I cannot change the class Test.java and Service.java. I can only modify my test

In my test, I call the method as: service.getTestObj(prod);
So I have to pass a valid Product object. And that will never throw JSONProcessingException. Is there a way to manipulate or reset the prod value (that is passed to the writeValueAsString method) with something like new Object() ?

1
What you need to do is mock your ObjectMapper, stub it so that it throws the exception, and inject it into Test. You'll need to change Test.java to allow that. I know you've said you can't, but you'll have to revisit that. (Not sure what the value is of unit testing code that you're not allowed to change - what do you do if a test fails?)Dawood ibn Kareem

1 Answers

0
votes
public class Test {

    private static final ObjectMapper mapper = new ObjectMapper();
    ..
    ..

    public static ObjectMapper getMapper(){
     return mapper;
    }
} 



@RunWith(MockitoJUnitRunner.class)
public class JunitTest {

  @Mock
  private ObjectMapper mapper;

    @Test(expected=InternalServerErrorException.class)
    public void test(){
     Mockito.when(Test.getMapper()).thenReturn(mapper);
     Mockito.when(mapper.writeValueAsString(Mockito.any())).thenThrow(JsonProcessingException.class);

Service service = new Service();
service.getTestObj(new Product());

            }
        }