Base i minne og testing

Og nå det mest interessante. Når du tester Hibernate-kode, vil du ofte ikke jobbe med en ekte base, men med en slags stubbe som implementerer minimal funksjonalitet.

Kan du forestille deg en stubbe som implementerer det meste av SQL Server-standarden? Ikke meg. Imidlertid er minnedatabaser utmerket som sådan. Det fungerer omtrent slik:

  • I @BeforeAll-metoden initialiserer vi databasetilkoblingen i minnet.
  • I @BeforeEach-metoden får vi sesjonen og åpner en transaksjon.
  • I @Test-metoden jobber vi med gjeldende økt og transaksjon.
  • I @AfterEach-metoden forplikter vi transaksjonen.
  • Og til slutt, i AfterAll-metoden, lukker vi forbindelsen til databasen.

Slik ser forberedelsene til testen ut:

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

Og slik ser selve testen ut med arbeidet til 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());
  }
}

testdata

Du kan også fylle testdatabasen med testdata.

Vanligvis lages to sql-filer for dette:

  • schema.sql inneholder et skript som lager tabeller i databasen
  • test-data.sql inneholder et skript som fyller tabeller med testdata

Tabelloppretting og testdata er vanligvis separert i forskjellige filer, siden deres egne grupper med testdata for forskjellige testgrupper nesten alltid vises.

Å kjøre disse filene ser slik ut:

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

Og oppsettmetoden din vil endre seg litt:

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