Interesting way to assert thrown exceptions in Spring Boot and AssertJ

You’re probably used to testing code that throws exceptions in either one of the following ways:

Using expected attribute of JUnit @Test  annotation, such as:

 @Test(expected = UserService.NoSuchUserException.class)
    public void deletesExistingUser() {
        final User existingUser = spy(new User());
        given(userRepository.findOne(eq("123"))).willReturn(existingUser);
        given(userRepository.save(eq(existingUser))).willReturn(existingUser);

        userService.deleteUser("123");

        verify(existingUser).setState(eq(User.State.DELETED));
    }

Or something like this, using JUnit’s @Rule annotation:

    @Rule
    ExpectedException thrown = ExpectedException.none();

    @Test
    public void deletesExistingUser() {
        thrown.expect(UserService.NoSuchUserException.class);
        thrown.expectMessage(format("User with id %s doesn't exist!", userId));
        final User existingUser = spy(new User());
        given(userRepository.findOne(eq("123"))).willReturn(existingUser);
        given(userRepository.save(eq(existingUser))).willReturn(existingUser);

        userService.deleteUser("123");

        verify(existingUser).setState(eq(User.State.DELETED));
    }

The one I found quite elegant and easy to use and understand comes from powerful AssertJ library, using static Assertions.assertThatThrownBy static method, as shown in the following test:

@Test
    public void failsDeletingUser() {
        final String userId = "123";
        given(userRepository.findOne(eq(userId))).willReturn(null);
        assertThatThrownBy(() -> userService.deleteUser(userId))
                .isInstanceOf(UserService.NoSuchUserException.class)
                .hasMessage(format("User with id %s doesn't exist!", userId));
    }

It receives instance of ThrowingCallable functional interface (Java 8) which is quite handy since you can pass lambda implementation (as shown). Given interface has only one method, which we implemented as lambda above. Interface looks like:

public interface ThrowingCallable {
    void call() throws Throwable;
}

In upcoming version 5 of JUnit framework there’s no more option to use expected attribute in @Test annotation. Having two options there, my favourite will be option coming from AssertJ library.

Let me know your thoughts!

Stay tuned and don’t forget to subscribe!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s