Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to rollback a Transaction in Quarkus Unit Tests?

I'm trying to learn some new things using Quarkus, and I kinda got stuck on something: I want to create some tests that are self sustained, I mean, I should be able to run each one independently of each other. I'm using Testcontainers(PostgreSQL) to run some component tests, but I would like to each @Test be able to run on a 'clean database', but I don't think that stoping the container and starting it once again for each @Test would be a good idea. I could have a @BeforeEach(container.dropColumn()) or @BeforeEach(container.truncateColumn()) but: 1 - I don't know if this is the better way, 2 - I don't know how to do this.

Given an hypothetical test scenario:

Scenario 1 - Pass

  • Register new User
  • Find User by its id
  • assert(one_user_on_db)

Scenario 2 - Fail

  • Try to Register new User with invalid data
  • Find all users
  • assert(zero_users_on_db)

The second test fail because the data from the first scenario is still on the database. Here, some code to help.

resources

    @Inject
    UserService userService;
    
    @POST
    @Transactional
    public Response saveUser(@Valid UserDto user){
        return Response.status(Response.Status.CREATED)
                .entity(userService.saveUser(user, user.getPassword())).build();
    }
    
    @GET
    public Iterable<User> findAll(){
        return userService.findAll();
    }

tests

@Test
void shouldSuccessfullyCreateUser(){
    User mockUser = MockUser.onlyMandatoryFields() //MockUser

    given()
            .body(mockUser)
            .contentType(ContentType.JSON)
            .when()
            .post("/users").prettyPeek()
            .then()
            .statusCode(Response.Status.CREATED.getStatusCode());

@Test
void shouldHaveAnEmptyDatabase(){
    User[] userList = given()
            .contentType(ContentType.JSON)
            .when()
            .get("/users").prettyPeek()
            .then()
            .extract()
            .response()
            .as(User[].class);

    assertEquals(0, userList.length);
}

I've already tried @TestTransaction as described in Quarkus Docs but no success.

I was looking for something like @DirtiesContext from Spring.

Anyway, I've got an open repository, if you want to look further into the code. The tests can be found here.

like image 804
Johnnes Souza Avatar asked Nov 15 '25 12:11

Johnnes Souza


1 Answers

@TestTransaction works properly when you test repositories or CDI beans directly.

I've already tried @TestTransaction as described in Quarkus Docs, but no success.

It works if tests run in the same transaction context as the tested code. Your REST resource works under a different transaction context than your test method; therefore, @TestTransaction will not work in your case. In your case the transaction gets committed at the end of the rest call; hence you cannot rollback it.

See an example of a working test validating the repository directly.

@Test
@TestTransaction
void shouldFail_whenCreatingNewLedgerWithUnrecognizedType() {
    //when/then
    assertThatThrownBy(() -> customSqlRepository.insertWithUnrecognizedType())
            .isInstanceOf(PersistenceException.class)
            .hasMessageContaining("Check constraint violation")
            .hasMessageContaining("LEDGER_ACCOUNT_TYPE IN(");
}
like image 96
Marek Żylicz Avatar answered Nov 17 '25 08:11

Marek Żylicz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!