Baza în memorie și testare

Și acum cel mai interesant. Când testați codul Hibernate, de foarte multe ori doriți să lucrați nu cu o bază reală, ci cu un fel de stub care implementează funcționalitate minimă.

Vă puteți imagina un stub care implementează majoritatea standardului SQL Server? Eu nu. Cu toate acestea, bazele de date în memorie sunt excelente ca atare. Funcționează cam așa:

  • În metoda @BeforeAll, inițializam conexiunea la baza de date în memorie.
  • În metoda @BeforeEach, obținem sesiunea și deschidem o tranzacție.
  • În metoda @Test, lucrăm cu sesiunea și tranzacția curentă.
  • În metoda @AfterEach, comitem tranzacția.
  • Și în final, în metoda AfterAll, închidem conexiunea la baza de date.

Iată cum arată pregătirea pentru test:

@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();
  }

Și așa arată testul în sine cu munca lui 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());
  }
}

date de testare

De asemenea, puteți completa baza de date de testare cu date de testare.

De obicei sunt făcute două fișiere sql pentru asta:

  • schema.sql conține un script care creează tabele în baza de date
  • test-data.sql conține un script care populează tabelele cu date de testare

Crearea tabelelor și datele de testare sunt de obicei separate în fișiere diferite, deoarece apar aproape întotdeauna propriile grupuri de date de testare pentru diferite grupuri de testare.

Executarea acestor fișiere arată astfel:

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()
}

Și metoda de configurare se va schimba puțin:

@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(“scema.sql”);
	runSqlScriptFile(“test-data.sql”);

  } catch (Throwable ex) {
      throw new ExceptionInInitializerError(ex);
  }
}