Дублирующие записи с разным Id при тестах JUNIT

При выполнении теста происходит дублирование записей с разным id

Тест:

@SpringBootTest
class SpringHibernateApplicationTests {

    @Autowired
    private PupilRepository pupilRepository;

    @Autowired
    private ClassRoomRepository classRoomRepository;

    @Autowired
    private TeacherRepository teacherRepository;

    @Autowired
    private PupilInClassRoomRepository pupilInClassRoomRepository;

    @BeforeEach
    @Rollback(value = false)
    public void contextLoads() {
        Pupil pupil = new Pupil();
        pupil.setName("Hello");
        pupil.setSurname("hello");

        Teacher teacher = new Teacher();
        teacher.setName("Alla");
        teacher.setSurname("Aronova");
        teacher.setDiscipline("Mat");

        ClassRoom classRoom = new ClassRoom();
        classRoom.setName("1A");

        PupilInClassRoom pupilInClassRoom = new PupilInClassRoom();
        teacher.setPupilInClassRoom(pupilInClassRoom);
        pupil.setPupilInClassRoom(pupilInClassRoom);
        classRoom.setPupilInClassRoom(pupilInClassRoom);

        pupilInClassRoomRepository.save(pupilInClassRoom);
        teacherRepository.save(teacher);
        pupilRepository.save(pupil);
        classRoomRepository.save(classRoom);

    }

    @Test
    public void createEntity() {
        Iterable<Pupil> allPupil = pupilRepository.findAll();
        for (Pupil pupil1 : allPupil) {
            System.out.println("Ученики");
            System.out.println("----------------------------");
            System.out.println(pupil1.getId() + " " +
                    pupil1.getName() + " " +
                    pupil1.getSurname());
            System.out.println("----------------------------");
        }

        Iterable<Teacher> allTeacher = teacherRepository.findAll();
        for (Teacher teacher1 : allTeacher) {
            System.out.println("Учителя");
            System.out.println("----------------------------");
            System.out.println(teacher1.getId() + " " +
                    teacher1.getName() + " " +
                    teacher1.getSurname() + " " +
                    teacher1.getDiscipline());
            System.out.println("----------------------------");
        }
        Iterable<ClassRoom> allClassRoom = classRoomRepository.findAll();
        for (ClassRoom classRoom1 : allClassRoom) {
            System.out.println("Класс");
            System.out.println("----------------------------");
            System.out.println(classRoom1.getId() + " "
                    + classRoom1.getName());
            System.out.println("----------------------------");
        }

        Iterable<PupilInClassRoom> allPupilInClassRoom = pupilInClassRoomRepository.findAll();
        for (PupilInClassRoom pupilInClassRoom1 : allPupilInClassRoom) {
            System.out.println("Ученики в классе");
            System.out.println("----------------------------");
            System.out.println(pupilInClassRoom1.getPupil().getId() + " " +
                    pupilInClassRoom1.getPupil().getName() + " " +
                    pupilInClassRoom1.getPupil().getSurname());

            System.out.println(pupilInClassRoom1.getTeacher().getId() + " " +
                    pupilInClassRoom1.getTeacher().getName() + " " +
                    pupilInClassRoom1.getTeacher().getSurname() + " " +
                    pupilInClassRoom1.getTeacher().getDiscipline());
            System.out.println(pupilInClassRoom1.getClassRoom().getId() + " " +
                    pupilInClassRoom1.getClassRoom().getName());
            System.out.println("----------------------------");
 }

    }

    @Test
    public void findPupilByTeacher() {
        System.out.println("Поиск ученика по учителю");
        System.out.println("----------------------------");
        Iterable<Pupil> finByTeacherOnPupil = pupilRepository.findByPupilInClassRoomTeacherName("Alla");
        for (Pupil pupil1 : finByTeacherOnPupil) {
            System.out.println(pupil1.getId() + " " +
                    pupil1.getName() + " " +
                    pupil1.getSurname());
        }
    }
}

Вывод в консоль createEntity():

Ученики
----------------------------
3 Hello hello
----------------------------
Ученики
----------------------------
7 Hello hello
----------------------------
Учителя
----------------------------
2 Alla Aronova Mat
----------------------------
Учителя
----------------------------
6 Alla Aronova Mat
----------------------------
Класс
----------------------------
4 1A
----------------------------
Класс
----------------------------
8 1A
----------------------------
Ученики в классе
----------------------------
3 Hello hello
2 Alla Aronova Mat
4 1A
----------------------------
Ученики в классе
----------------------------
7 Hello hello
6 Alla Aronova Mat
8 1A
----------------------------

Вывод в консоль findPupilByTeacher():

Поиск ученика по учителю
----------------------------
3 Hello hello

Если засунуть тело метода createEntity в contextLoads, то все выводится корректно, если пытаюсь разносить, то получается некорректный вывод.


Ответы (1 шт):

Автор решения: Roman Konoval

Метод помеченый @BeforeEach выполняется перед каждым тестом.

У вас два теста, вот он и выполнился дважды и создал данные дважды.

createEntity выполнялся вторым, поэтому он увидел результаты обоих выполнений.

Один способ это исправить это делать инициализацию данных в БД один раз. Для этого можно воспользоваться аннотацией @BeforeAll вместо @BeforeEach а так же добавить контфигурацию для тестового класса, чтоб можно использовать `BeforeAllz на не статическом методе:

@TestInstance(Lifecycle.PER_CLASS)
@SpringBootTest
class SpringHibernateApplicationTests {
  ...
  @BeforeAll
  @Rollback(value = false)
  public void contextLoads() {
    ...
  }
}
→ Ссылка