@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Song favoriteSong;
@ManyToOne(fetch = FetchType.LAZY)
private Book favoriteBook;
...
}
AssertJ 3.16.0 has just been released. It has a feature I contributed to allow testing the (root) cause of an exception.
This blog post will show how to use this to our advantage.
Let’s get started with a simple Spring Boot application using Spring Data JPA.
We will have 3 entities: Book, Song and User
A User can have exactly 1 favorite book and 1 favorite song.
The book and the song have to be in the database already before the user can make it a favorite of his.
Check the sources on Github for the full code.
This is how the User looks like:
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Song favoriteSong;
@ManyToOne(fetch = FetchType.LAZY)
private Book favoriteBook;
...
}
The code also has BookRepository, SongRepository and UserRepository.
The test we will focus on is the UserRepositoryTest:
@Test
void testUnableToSaveUserIfBookNotInDatabase() {
Book book = new Book();
book.setTitle("AssertJ in action");
User user = new User();
user.setFavoriteBook(book);
assertThatExceptionOfType(IllegalStateException.class)
.isThrownBy(() -> {
repository.save(user);
entityManager.flush();
})
.havingCause()
.withMessageMatching(".*object references an unsaved transient instance.*User.favoriteBook.*");
}
What we test here is that if a User has a favorite Book that is not yet saved in the database, we get an IllegalStateException.
Not only that, but we also check that there is a cause (via havingCause()) and that this cause should have a particular message where the User.favoriteBook field is present.
A similar test can be done if a Song is not yet saved in the database:
@Test
void testUnableToSaveUserIfSongNotInDatabase() {
Song song = new Song();
song.setTitle("Bee Gees - Stayin' Inside");
User user = new User();
user.setFavoriteSong(song);
assertThatExceptionOfType(IllegalStateException.class)
.isThrownBy(() -> {
repository.save(user);
entityManager.flush();
})
.havingCause()
.withMessageMatching(".*object references an unsaved transient instance.*User.favoriteSong.*");
}
See Checking cause and root cause in the AssertJ documentation for more information about this handy function.