ldepablo
ldepablo

Reputation: 424

@Transaction annotation for integration testing in Spring Boot

I have the following method in a JpaRepository that simply updates the parent_id column for every row with a specific value in that column. It works perfectly in pure SQL but it failed in Spring Data. I think it's due to just some problem with the transaction scope, because the update is done (first assert passes). It's just I can't see what code is changed in DB. I want to use the

@Transactional
@Rollback

because I guess this is best practice. Is there any way I can see what's don in the code from my test method?

@Modifying
@Query("update MovementCategory mc set mc.parentId = :newParentId where mc.parentId = :previousParentId and mc.userId = :userId")
int updateChildrenParentId(@Param("userId") long userId, @Param("previousParentId") long previousParentId, @Param("newParentId") long newParentId);

I've created a simple integration test that checks that changes are correctly set in DB, but it doesn't seem to work and I can't get to see why. I thought it could be because of transaction scope but I did a smaller test and discarded it, so no idea. The following is the integration test.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MySpringBootMavenApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port:0")
@Transactional
@Rollback
public class MovementCategoryRepositoryIT {

private static final long USER_ID = -1L;

@Autowired MovementCategoryRepository repo;

@Test
public void testUpdateChildrenParentId() {

    long newParentId= -9723854;
    long previousParentId = -1239842;

    MovementCategory mc1 = getFilled(null, "DELETE ME");
    mc1.setParentId(previousParentId);
    mc1 = repo.saveAndFlush(mc1);

    int updates = repo.updateChildrenParentId(USER_ID, previousParentId, newParentId);

    // First assert passes, so there update is done
    assertEquals(1, updates);

    MovementCategory children1 = repo.findOneByIdAndUserId(mc1.getId(), USER_ID);

    // Second one fails
    assertEquals(newParentId, children1.getParentId().longValue());

}

Result:

java.lang.AssertionError: expected:<-9723854> but was:<-1239842>
    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotEquals(Assert.java:834)
    at org.junit.Assert.assertEquals(Assert.java:645)
    at org.junit.Assert.assertEquals(Assert.java:631)
    at com.ldepablo.repository.MovementCategoryRepositoryIT.testUpdateChildrenParentId(MovementCategoryRepositoryIT.java:171)
    ...

Upvotes: 1

Views: 5739

Answers (1)

Christian
Christian

Reputation: 14061

You need to start the transaction for reading explicitly and also roll back the transaction explicitly as the REST calls are in a different session than the test. Use TransactionTemplate as described in this answer.

(Answering too late, of course; but this was the first hit on the search engine)

Upvotes: 1

Related Questions