I have a simple reactive CRUD application made with Quarkus while following these two articles: Getting started reactive and Hibernate reactive panache
I am trying to test my service methods, but before that I'm trying to see how the example test works. This is the example test from the article:
import io.quarkus.test.hibernate.reactive.panache.TransactionalUniAsserter;
@QuarkusTest
public class SomeTest {
@Test
@RunOnVertxContext
public void testEntity(TransactionalUniAsserter asserter) {
asserter.execute(() -> new MyEntity().persist());
asserter.assertEquals(() -> MyEntity.count(), 1l);
asserter.execute(() -> MyEntity.deleteAll());
}
}
When I try to replicate the test like below, the test always passes no matter what I set the expected count to.
Here is my test file with the test case that is green.
`@QuarkusTest
@RunOnVertxContext
class AuthorServiceTest {
@Inject
AuthorService service;
@Test
@RunOnVertxContext
public void testGetAllAuthors(TransactionalUniAsserter a) {
a.execute(() -> new Author("J.K.", "Rowling", LocalDate.of(1965, 7, 31)).persist());
a.assertEquals(Author::count, 3L);
a.execute(Author::deleteAll);
}
}`
I am also trying to find out how to test service methods that return Uni types. I can't find any resources online that show this. Most of the ways to test seem to throw No current Vertx context found.
Here is how my model looks like:
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "authors")
public class Author extends PanacheEntity {
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String surname;
@Column(nullable = false)
private LocalDate dateOfBirth;
}
Here is my service:
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.panache.common.Sort;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.core.Response;
import um.feri.model.Author;
import java.util.List;
@ApplicationScoped
public class AuthorService {
public Uni<List<Author>> getAllAuthors() {
return Author.listAll(Sort.by("surname"));
}
public Uni<Response> getAuthorById(Long id) {
return Author.findById(id)
.onItem().ifNotNull().transform(author -> Response.ok(author).build())
.onItem().ifNull().continueWith(() -> Response.status(Response.Status.NOT_FOUND).build());
}
public Uni<Author> findIfAuthorExists(Author author) {
return Author.find("name = ?1 and surname = ?2 and dateOfBirth = ?3",
author.getName(), author.getSurname(), author.getDateOfBirth())
.firstResult();
}
public Uni<Author> addAuthor(Author author) {
return findIfAuthorExists(author)
.onItem().ifNotNull().transform(existingAuthor -> existingAuthor)
.onItem().ifNull().switchTo(() -> Panache.withTransaction(author::persist).replaceWith(author));
}
public Uni<Response> updateAuthor(Long id, Author updatedAuthor) {
return Author.<Author>findById(id)
.onItem().ifNotNull().transformToUni(existingAuthor -> {
existingAuthor.setName(updatedAuthor.getName());
existingAuthor.setSurname(updatedAuthor.getSurname());
existingAuthor.setDateOfBirth(updatedAuthor.getDateOfBirth());
return Panache.withTransaction(existingAuthor::persist)
.replaceWith(Response.ok(existingAuthor).build());
})
.onItem().ifNull().continueWith(Response.status(Response.Status.NOT_FOUND).build());
}
public Uni<Response> deleteAuthor(Long id) {
return Panache.withTransaction(() -> Author.deleteById(id))
.map(deleted -> deleted
? Response.ok().status(Response.Status.NO_CONTENT).build()
: Response.ok().status(Response.Status.NOT_FOUND).build());
}
}
Is it better to just test the resource and leave the service methods alone? The code for this project is available on my Github
I tried using this solution but every test passes, even if I compare 2 to 3;
I've changed a couple of things and now the test seems to work:
Upgrade Quarkus to 3.14.2. In the pom.xml
:
<properties>
...
<quarkus.platform.version>3.14.2</quarkus.platform.version>
...
</properties>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-vertx</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-hibernate-reactive-panache</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
Remove quarkus-reactive/src/test/java/um/feri/TransactionalUniAsserterInterceptor.java
and update the test to:
package um.feri.services;
import java.time.LocalDate;
import org.junit.jupiter.api.Test;
import io.quarkus.test.hibernate.reactive.panache.TransactionalUniAsserter;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.vertx.RunOnVertxContext;
import jakarta.inject.Inject;
import um.feri.model.Author;
@QuarkusTest
class AuthorServiceTest {
@Test
@RunOnVertxContext
public void testGetAllAuthors(TransactionalUniAsserter a) {
a.execute( () -> new Author( "J.K.", "Rowling", LocalDate.of( 1965, 7, 31 ) ).persist() );
// Panache doesn't support method reference
a.assertEquals( () -> Author.count(), 6L );
a.execute( () -> Author.deleteAll() );
}
}
Optional, add quarkus.hibernate-orm.log.sql=true
in the application.properties
. It will show you the SQL getting executed.
You should be able to test services the same way, for example:
@Inject
AuthorService service;
@Test
@RunOnVertxContext
@Order( 1 )
public void testGetAllAuthors(TransactionalUniAsserter a) {
a.execute( () -> new Author( "J.K.", "Rowling", LocalDate.of( 1965, 7, 31 ) ).persist() );
a.assertEquals( () -> Author.count(), 6L );
}
@Test
@RunOnVertxContext
@Order( 2 )
public void testService(TransactionalUniAsserter a) {
a.assertThat( () -> service.getAllAuthors(), authors -> {
Assertions.assertNotNull( authors );
Assertions.assertEquals( 6, authors.size() );
} );
}