1. База в пам'яті та тестування

А тепер найцікавіше. Під час тестування коду Hibernate дуже часто хочеться працювати не з реальною базою, а з якоюсь заглушкою, що реалізує мінімальну функціональність.

А ти уявляєш заглушку, яка реалізує більшу частину стандарту SQL-сервера? Я — ні. Однак на роль такої відмінно підходять бази даних у пам'яті. Працює це приблизно за такою схемою:

  • У методі @BeforeAll ми ініціалізуємо з'єднання з базою даних у пам'яті.
  • У методі @BeforeEach ми отримуємо сесію та відкриваємо транзакцію.
  • У методі @Test ми працюємо з поточною сесією та транзакцією.
  • У методі @AfterEach ми дотримуємося транзакції.
  • І нарешті, у методі AfterAll ми закриваємо з'єднання з базою.

Ось як виглядає підготовка до роботи тесту:


@Test
public class HelloTest {
  private static SessionFactory sessionFactory = null;
  private Session session = null;
 
  @BeforeAll
  static void setup(){
    try {
  StandardServiceRegistry standardRegistry = New StandardServiceRegistryBuilder()
      .configure("hibernate-test.cfg.xml").build();
 
  Metadata metadata = New MetadataSources(standardRegistry)
      .addAnnotatedClass(Employee.class)
      .getMetadataBuilder()
      .build();
 
      sessionFactory = metadata.getSessionFactoryBuilder().build();
 
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
  }
 
  @BeforeEach
  void setupThis(){
      session = sessionFactory.openSession();
      session.beginTransaction();
  }
 
  @AfterEach
  void tearThis(){
      session.getTransaction().commit();
  }
 
  @AfterAll
  static void tear(){
      sessionFactory.close();
  }

А ось так виглядає сам тест із роботою Hibernate:


  @Test
public class HelloTest {
 
  @Test
  void createSessionFactoryWithXML() {
       Employee emp = New Employee();
       emp.setEmail("demo-user@mail.com");
       emp.setFirstName("demo");
       emp.setLastName("user");
 
       Assertions.assertNull(emp.getEmployeeId());
       session.persist(emp);
       Assertions.assertNotNull(emp.getEmployeeId());
  }
}

2. Тестові дані

Також можеш заповнити свою тестову базу тестовими даними.

Зазвичай для цього роблять два sql-файли:

  • schema.sql — містить скрипт, який створює таблиці в базі
  • test-data.sql — містить скрипт, який заповнює таблиці тестовими даними

Створення таблиці та тестові дані зазвичай розносять до різних файлів, оскільки практично завжди з'являються свої групи тестових даних для різних груп тестів.

Виконання цих файлів виглядає так:


  void runSqlScriptFile(String filePath){
    String sqlScript = new String( Files.readAllBytes(Paths.get(filePath)) );
    Session session = sessionFactory.openSession();
        Query query = session.createNativeQuery("BEGIN" + sqlScript + "END;");
        query.executeUpdate()
  }

І твій метод setup трохи зміниться:


  @BeforeAll
  static void setup(){
    try {
  StandardServiceRegistry standardRegistry = New StandardServiceRegistryBuilder()
      .configure("hibernate-test.cfg.xml").build();
 
  Metadata metadata = New MetadataSources(standardRegistry)
      .addAnnotatedClass(Employee.class)
      .getMetadataBuilder()
      .build();
 
  sessionFactory = metadata.getSessionFactoryBuilder().build();
  runSqlScriptFile(“schema.sql”);
  runSqlScriptFile(“test-data.sql”);
 
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
  }