Home > Net >  Mockito: Cannot throw exception in Java Unit Test
Mockito: Cannot throw exception in Java Unit Test

Time:04-13

I have the following service and test methods and I am trying the code execute catch (ApplicationException e) { } block.

public abstract class ApplicationException extends RuntimeException {
    // ....
}
public void create(Request request) {
    
    try {
        // ...
    } catch (ApplicationException e) {
        // I want the code hits this block and check the values in here
    } 
}

Here is the test method:

@InjectMocks
private ProductServiceImpl productService;


@Test
public void test() {

    // variable defnitions and stubbings (code omitted)

    willAnswer( invocation -> { throw new RuntimeException("abc msg"); })
        .given(productService).create(request);

    // or
    // doThrow(new RuntimeException()).when(productService).create(request);


    // service method call
    productService.create(Request request);
}

When I debug the code, I get error on doThrow line:

org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock!

So, how can I solve the problem?

CodePudding user response:

As @Jesper mentioned in comment you are not using Mockito properly.

For your test case you need to test that your ProductService.create method will handle an error in a given scenario. Let's imagine that your code looks like this.

class ProductService {
    private SomeOtherService someOtherService;
    
    public void create(Request request) {
    
    try {
        someOtherService.execute();    
    } catch (ApplicationException e) {
        // I want the code hits this block and check the values in here
enter code here
        throw new MyException(e); // Here you can do something else
    } 
}

So someOtherService.execute can throw ApplicationException. We need to test if our ProductService.create will catch that exception and do some processing. In the example we will just throw a different type of exception.

@Mock
private SomeOtherService mockOtherService;
@InjectMocks
private ProductServiceImpl productService;


@Test
public void test() {
  
   doThrow(new ApplicationException()).when(someOtherService).execute();
    
   given(productService.create(request)).willThrow(new MyException());
}

So main difference from your example is that we are telling the SomeOtherService mock what it should do when execute method is called. This is allowed and Mockito knows how to work with mocks.

In your example you were trying to pass a real object not a mock. @InjectMock annotation is a shorthand for this

this.productService = new ProductService(mockSomeOtherService);

So it creates a new object with its dependency mocked. More about this you can find here https://stackoverflow.com/a/16467893/2381415.

I didn't run this code or test it so do not C/P it.

Hope it helps you understand what was wrong with your approach.

  • Related