简体   繁体   中英

Spring Data JPA database changes after each method don't roll back in integration tests

I am using JUnit 5 with Spring boot 2.2.4 for integration testing my Spring Boot application code with MySQL 5.7 database but the changes that a previous test method makes to database aren't rolled back causing errors in the ones that follow.

I've tried answers from different stackoverflow posts such as adding @Transactional (from Spring), @Rollback (method as well as class level), @TestExecutionListeners(listeners = {TransactionalTestExecutionListener.class}) . I've tested these options individually (as well as in combination) but adding them in the test code together.

This is my test code:

@DataJpaTest
@Transactional
@Rollback
@ExtendWith(SpringExtension.class)
@Import({UserUsecasesImpl.class})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserUsecasesImplINTTest {

    @Autowired
    private TestEntityManager entityManager;
    @Autowired
    @Spy
    private UserRepository userRepository;
    @Autowired
    private UserUsecases userUsecases;

    @Test
    void injectedComponentsAreNotNull(){
        assertNotNull(entityManager);
        assertNotNull(userRepository);
        assertNotNull(userUsecases);
    }

    @Test
    @Rollback
    void Create_EntityAlreadyExists_ReturnsException() {
        // set up
        User expected = UserFixture.user1.toBuilder().build();
        // entityManager.persistAndFlush(expected);
        userRepository.saveAndFlush(expected);

        // execute
        User actual = userUsecases.create(expected);

        // verify
        assertEquals(expected, actual);
        verify(userRepository).findOne(any(Example.class));
        verify(userRepository, never()).save(any(User.class));
        verifyNoMoreInteractions();
    }

    @Test
    void Find_WhenUserPresent_ReturnUser() {
        // // set up
        User expected = UserFixture.user1.toBuilder().build();
        entityManager.persistAndFlush(expected);

        // execute
        User actual = userRepository.find(expected);

        // verify
        assertEquals(expected, actual);
    }

    @Test
    // @Transactional
    void Find_WhenUserNotPresent_ReturnNull() {
        // // set up
        User expected = UserFixture.user1.toBuilder().build();
        // entityManager.persistAndFlush(UserFixture.user2.toBuilder().build());

        // execute
        User actual = userUsecases.find(expected);

        // verify
        assertNull(actual);
    }
}

UserUsecasesImpl is the class that I am trying to test which contains usecases such as creating a user, finding a user, get all users, etc. There is no special configuration anywhere else in the code.

Please implement following fixes and let me know if problem still there:

  1. Remove all @Transactional and @Rollback . Keep @DataJpaTest which by default makes all of your tests @Transactional and therefore by default will roll them all back.
  2. don't use saveAndFlush . The flush part is flushing save operation into the database and most likely causes your issue. Use save instead. More here https://www.baeldung.com/spring-data-jpa-save-saveandflush
  3. If you are expecting exception assert it with assertThrows .

In general try not to throw every single annotation you know into the mix at the same time. Add them one at a time as you need them, try to understand what they do.

What is UserUseCases and why does it do most of the logic I would expect the Repository class to do?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM