@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.