Base in memoria e test

E ora il più interessante. Quando si testa il codice di Hibernate, molto spesso si desidera lavorare non con una base reale, ma con una sorta di stub che implementa funzionalità minime.

Riesci a immaginare uno stub che implementa la maggior parte dello standard di SQL Server? Io no. Tuttavia, i database in memoria sono eccellenti in quanto tali. Funziona più o meno così:

  • Nel metodo @BeforeAll, inizializziamo la connessione al database in memoria.
  • Nel metodo @BeforeEach, otteniamo la sessione e apriamo una transazione.
  • Nel metodo @Test, lavoriamo con la sessione e la transazione correnti.
  • Nel metodo @AfterEach, eseguiamo il commit della transazione.
  • E infine, nel metodo AfterAll, chiudiamo la connessione al database.

Ecco come si presenta la preparazione per il 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();
  }

Ed ecco come appare il test stesso con il lavoro di 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());
  }
}

dati di test

Puoi anche popolare il tuo database di test con i dati di test.

Di solito vengono creati due file sql per questo:

  • schema.sql contiene uno script che crea tabelle nel database
  • test-data.sql contiene uno script che popola le tabelle con i dati di test

La creazione della tabella e i dati di test sono generalmente separati in file diversi, poiché i propri gruppi di dati di test per diversi gruppi di test vengono quasi sempre visualizzati.

L'esecuzione di questi file è simile a questa:

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

E il tuo metodo di configurazione cambierà un po':

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