Search code examples
javajunittddjunit4bdd

Given, when, then convention together with exception handling. With Mockito and JUnit


It's a good practice to divide test cases into 3 sections: Given, When, Then.

But in JUnit common way to handle exceptions is using ExpectedException @Rule.

The problem is ExpectedException::expect() must be declared before //when section.

public class UsersServiceTest {

// Mocks omitted    

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void signUp_shouldCheckIfUserExistsBeforeSign() throws ServiceException {
    // given - its ok
    User user = new User();
    user.setEmail(EMAIL);
    when(usersRepository.exists(EMAIL)).thenReturn(Boolean.TRUE);

    // then ???
    thrown.expect(UserAlreadyExistsServiceException.class);

    // when???
    usersService.signUp(user);

}
}

Does anyone know some good convention or library for better handling exceptions in tests?


Solution

  • First of all, I think your tests are ok even if some don't exactly follow the given/when/then sequence, but good for you if you want to standardize the organization of your tests for improved readability.

    There are lots of valid ways to expect an exception in JUnit, as described in this StackOverflow page. I think the one that seems to fit in with the given/when/then organization would be:

    @Test
    public void signUp_shouldCheckIfUserExistsBeforeSign() throws ServiceException {
    
        // GIVEN
        User user = new User();
        user.setEmail(EMAIL);
        when(usersRepository.exists(EMAIL)).thenReturn(Boolean.TRUE);
    
        // WHEN 
        try {
            usersService.signUp(user);
    
        // THEN
            // expecting exception - should jump to catch block, skipping the line below:
            Assert.fail("Should have thrown UserAlreadyExistsServiceException");         
        }catch(UserAlreadyExistsServiceException e) {
            // expected exception, so no failure
        }
        // other post-sign-up validation here
    }