1
votes

I have a Book model class in my application that looks like this:

@Entity
public class Book extends PanacheEntity{
    public String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

In my test class, I create an instance of this class and call persistAndFlush(). Next, I make an HTTP call with rest assured to the controller. I pass the id of the newly created and persisted entity as path param to the controller.

@QuarkusTest
public class GreetingResourceTest {

    @Test
    @Transactional
    public void testBookEndpoint() {
        Book book= new Book();
        book.title="Quarkus is awesome";
        book.persistAndFlush();
        assertTrue(book.isPersistent());
        given()
          .when().get("/hello/"+book.id)
          .then()
             .statusCode(200)
             .body(is("Quarkus is awesome"));
    }
}

The controller gets the request successfully. It receives the book and the id. BUT: when the controller query the database, the entity doesn't exist.

The full code below:

@Path("/hello")
public class GreetingResource {

    @GET
    @Path("/{id}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getBook(@PathParam("id") Long id) {
        Book book=Book.findById(id);
        return book.title; //NullPointerException. Book cannot be found
    }
}

Book.findById(id) returns null. Why?

1
Hi Paul, is a slash missing in "/library/book/"+id? Can you show the code of the rest resource/controller?Edgar Domingues

1 Answers

1
votes

this issue is caused by the the visibility of transactions involved. Although there is a call to book.persistAndFlush(), the transaction wrapping public void testBookEndpoint() has not yet been committed. Therefore, the new book is not yet visible to the transaction in public String getBook(@PathParam("id") Long id).

You need ensure the transaction inserting the book is committed before testing the rest endpoint, to ensure that the new book is visible in the database to the rest call that is retrieving it, e.g.

@QuarkusTest
public class GreetingResourceTest {
    static Book book;

    @BeforeAll
    @Transactional
    public static void setupEntities(){
        book = new Book();
        book.title="Quarkus is awesome";
        book.persistAndFlush();
        assertTrue(book.isPersistent());
    }

    @Test
    public void testBookEndpoint() {
        given()
                .when().get("/hello/"+book.id)
                .then()
                .statusCode(200)
                .body(is("Quarkus is awesome"));
    }
}