21

I have a method which I am trying to test

public List<User> getUsers(String state) {

        LOG.debug("Executing getUsers");

        LOG.info("Fetching users from " + state);
        List<User> users = null;
        try {
            users = userRepo.findByState(state);
            LOG.info("Fetched: " + mapper.writeValueAsString(users));
        }catch (Exception e) {
            LOG.info("Exception occurred while trying to fetch users");
            LOG.debug(e.toString());
            throw new GenericException("FETCH_REQUEST_ERR_002", e.getMessage(), "Error processing fetch request");
        }
        return users;
    }

Below is my test code:

@InjectMocks
    private DataFetchService dataFetchService;

    @Mock
    private UserRepository userRepository;

@Test
    public void getUsersTest_exception() {
        when(userRepository.findByState("Karnataka")).thenThrow(new Exception("Exception"));
        try {
            dataFetchService.getUsers("Karnataka");
        }catch (Exception e) {
            assertEquals("Exception", e.getMessage());
    }
    }

Below is my UserRepository interface:

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {

public List<User> findByState(String state);
}

When the run my test as Junit test, it gives me following error:

org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: java.lang.Exception: Exception occurred

Any idea on how to resolve this? Thanks in advance.

sk17261205
  • 421
  • 1
  • 5
  • 12
  • The error message is extremely specific: Your `findByState` method can't throw `Exception`. Note in particular that (1) you should catch the most specific exception possible, in this case `DataAccessException`, and (2) it's harmful to troubleshooting to mask the underlying exception; make sure to use the chained constructor that takes `Throwable cause`. – chrylis -cautiouslyoptimistic- Sep 27 '19 at 05:48

3 Answers3

31

You should use RuntimeException or subclass it. Your method has to declare checked exception (example: findByState(String state) throws IOException;) otherwise use RuntimeException:

 when(userRepository.findByState("Karnataka"))
       .thenThrow(new RuntimeException("Exception"));
i.bondarenko
  • 3,442
  • 3
  • 11
  • 21
13

If you can modify the source code, then use RuntimeException or extend the RuntimeException.class as @i.bondarekno and @Gayan mentioned

In some cases, we can't change the source code, that time you can use the mockito do answer to throw checked exception.

 doAnswer((invocation) -> {
            throw new IOException("invalid");
        }).when(someClass).someMethodName();
Sivaram Rasathurai
  • 5,533
  • 3
  • 22
  • 45
0

According to the example provided, one should ideally look for a GenericException

when(userRepository.findByState("Karnataka")).thenThrow(RuntimeException.class);

GenericException exception = assertThrows(GenericException.class, () -> 
                                       userRepository.findByState("Karnataka"));
Gayan Weerakutti
  • 11,904
  • 2
  • 71
  • 68