Инициализировать базу данных перед тестами JUnit5 и Spring

В моем проекте используется Spring, Hibernate ant JUnit 5. Каков наилучший подход к инициализации БД перед всеми тестами?

Вот как я устал это делать:

class DbCreatorService {
   @Autowired
   private Service1;
   @Autowired
   private Service2;
....
}

@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext.xml")
@Transactional
class MyTest {

    @BeforeAll
    static void initDatabase(@Autowired DbCreatorService dbCreatorService ) {
        dbCreatorService.initDB()
    }
}

Когда я звоню sessionFactory.getCurrentSession() где-то в initDB(), я получаю: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread. sessionFactory внедряется с помощью @Autowired.

Что делает метод initDB()? Инициализирует подключение к БД или подготавливает таблицы с данными перед тестами?

Gabriel Robaina 28.06.2019 21:03

он создает базу данных и вставляет данные в таблицы

telebog 01.07.2019 10:02

Я обновил свой вопрос с более подробной информацией

telebog 01.07.2019 10:09

Я делал это со встроенным H2 в тестовой области. У меня есть код с работы, чтобы показать вам. Завтра постараюсь написать ответ.

Gabriel Robaina 02.07.2019 01:01
1
4
4 899
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Чего мы пытаемся достичь?

Сценарий базы данных, который удобен для тестирования и может быть легко настроен до и после каждого тестового примера.

Как я этого добился

Я использовал встроенную базу данных H2 в области тестирования с настройкой базы данных с помощью сценария SQL перед каждым тестовым случаем.

  1. Во-первых, добавьте H2 в зависимость области тестирования от pom.xml (вы используете Maven, верно?).

    <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>

  2. Затем настройте класс тестов JUnit.

SampleTestClass.java

@SpringBootTest // Allows you to autowire beans on your test class

@AutoConfigureTestDatabase // Configures a database on test scope instead of your regular database config.

@RunWith(SpringRunner.class) // Runs test context with SpringRunner.class

@SqlGroup({ // Setups .sql files to be run on specific triggers. In this case, before each test method the script will be ran.
        @Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:beforeTest.sql"),
})

@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) // The spring application context will be considered "dirty" before each test method, and will be rebuilt. It means that
// your autowired beans will not carry any data between test cases.

public class SampleTestClass {

// write your test cases here...
}
  1. В пути к классам теста добавьте файл передтестом.sql, который будет запускаться перед каждым методом тестирования. Этот файл может включать в себя создание таблицы и вставку некоторых данных для вашей работы. Если вам нужно какое-то дополнительное взаимодействие с базой данных, вы всегда можете иметь метод, аннотированный @Before в своем тестовом классе. Этот метод будет запускаться перед каждым тестовым случаем.

Спасибо за подробное объяснение, но мне нужен был способ инициализировать БД перед всеми методами тестирования, а не для каждого метода тестирования. Также я использую JUnit5 и только Spring, а не SpringBoot.

telebog 02.07.2019 16:13

Извините за неправильное понимание ваших реквизитов. Тем не менее, я считаю, что вы все еще можете использовать некоторые из этих методов для настройки вашей БД для тестов. Если вам нужно инициализировать БД перед ВСЕМИ тестами, как вы сказали, аннотация JUnit @Before - ваш лучший выбор. Единственная разница между загрузкой Spring и Spring — это аннотации конфигурации контекста, и я полагаю, что вы уже разобрались с ними в своем коде.

Gabriel Robaina 04.07.2019 14:12

Я использую @Before с флагом, поэтому я инициализирую БД только один раз, но это выглядит как взлом.

telebog 04.07.2019 18:01

Использование before для общих настроек набора тестов — самое элегантное решение.

Gabriel Robaina 04.07.2019 19:23

Была ли эта установка полезной? Вы нашли более элегантное решение?

Gabriel Robaina 22.07.2019 04:01

Я добавил ответ с моим окончательным решением

telebog 22.07.2019 16:04
Ответ принят как подходящий

Мои тесты только что читали из БД, и я хотел инициализировать БД только один раз перед всеми тестами. Мое окончательное решение:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext.xml")
@Transactional
class MyTest {
    @Autowired 
    private DbCreatorService dbCreatorService;

    @BeforeAll
    void initDatabase() {
        dbCreatorService.initDB()
    }
}

Как это работает, когда метод, отмеченный @BeforeAll, должен быть статическим?

PetarMI 05.10.2020 18:07

Это работает из-за @TestInstance(TestInstance.Lifecycle.PER_CLASS) baeldung.com/java-beforeall-afterall-нестатический

telebog 22.10.2020 15:39

Другие вопросы по теме