0

I'm setting up unit tests for my company application. It's set up to create a new docker container of the database for every test, so each test has a fresh database to work with. However, I get an IO error when I attempt to reuse EntityManagerFactory between tests now. I tried instantiating a new EMF for each test but it takes about 74% of the runtime just to call Persistence.createEntityManagerFactory, which is really slowing down the test suite. Is it possible to either: reuse the EMF between tests by connecting to the new database container at the start of each test or somehow reduce the time taken to create a new instance of EntityManagerFactory?

1 Answer 1

0

I figured this out. So first thing, I moved the call to createEntityManagerFactory to run before any tests run, so it will only run once for the whole test suite. This caused a problem because the EMF will attempt to connect to the database when it is created. I removed the connection info from persistence.xml and it no longer attempts to create the connection at that point.

Then I added the connection info at the time that I create an EntityManager. I couldn't figure out a way to do this through the JPA interface so I had to unwrap the hibernate SessionFactory. This is what it looks like:

Connection connection = null;
try {
    connection = DriverManager.getConnection("jdbc:postgresql://localhost:" + port + "/avm_test",
                                             "postgres",
                                             "postgres");
} catch (SQLException e) {
    throw new RuntimeException(e);
}
entityManager = entityManagerFactory.unwrap(SessionFactory.class).withOptions().connection(connection).openSession();

Not directly a part of this question, but I couldn't create multiple containers with the same port exposed, so now I dynamically generate the port for each container to expose, and pass that port to this code to connect to the database. To get an available port dynamically I used ServerSocket.

// Creating a socket with parameter 0 assigns an available port.
socket = new ServerSocket(0);
port = String.valueOf(socket.getLocalPort());

Not the answer you're looking for? Browse other questions tagged or ask your own question.