Some questions about using Hibernate in tests

302 views
Skip to first unread message

Aditya Prasad

unread,
Aug 21, 2020, 1:30:28 PM8/21/20
to dropwiz...@googlegroups.com
Hi all,

I'm having some difficulties making Hibernate work in DropWizard. I'm new to both Hibernate and DW, so I apologize if my questions are stupid.

I set up my tests like so:
@ExtendWith(DropwizardExtensionsSupport.class)
public class UpdateTest {
private SessionFactory sessionFactory;

public DAOTestExtension database = DAOTestExtension.newBuilder()
.addEntityClass(Foo.class)
.build();

@BeforeEach
public void setup() {
sessionFactory = database.getSessionFactory();
}
There are a few things I'm not understanding.

1) I can't use this SessionFactory as I normally would. The first of these createQuery calls succeeds, and the second fails (with "Calling method 'createQuery' is not valid without an active transaction"):
   try (Session session = sessionFactory.openSession()) {
       Transaction transaction = session.beginTransaction();
       session.createQuery(...).executeUpdate();
       sessionFactory.getCurrentSession().createQuery(...).executeUpdate();
       transaction.commit();
   }
I understand that I'm supposed to use database.inTransaction(), but I don't understand why the above fails. Maybe this won't matter so much once I get used to it.

2) I can't figure out whether it's possible to set up config. For example, can I configure the driver, jdbc URL, dialect, etc? Or is there no way to connect to a real db? Maybe I'm mixing concerns here, but I'd like my DAO tests to also test things like db constraints.

Normally this can be done with (org.hibernate.cfg.)Configuration or (io.dropwizard.db.)DataSourceFactory, but I don't think I can do that here. Or it can be done through a hibernate.cfg.xml or hibernate.properties, but Hibernate doesn't find hibernate.cfg.xml, and loads but doesn't use settings from hibernate.properties.

Thanks,
Aditya

Dimas Guardado

unread,
Aug 23, 2020, 1:36:18 AM8/23/20
to dropwizard-user
Hi Aditya,

1) The reason the second `createQuery` call fails is because it is using a *different* session from the one you created in the initial `try` line. This is because `DaoTestExtension` opens a session and binds it to `getCurrentSession()` before every test method runs: https://github.com/dropwizard/dropwizard/blob/v2.0.12/dropwizard-testing/src/main/java/io/dropwizard/testing/common/DAOTest.java#L146 . The first `createQuery` runs against the `try` session which has a transaction, while the second runs against the `DAOTest` session which has no knowledge of the transaction you created. I haven't tested this myself, but I expect you use `sessionFactory.getCurrentSession()` everywhere in your test instead of creating your own session, it'll work the way you expect. The only other note would be that the framework and testing tools are set up to use hibernate within the context of a DAO class. I expect it'll be easier for both your app code and your test code to keep hibernate calls in one of those classes: https://www.dropwizard.io/en/latest/manual/hibernate.html#data-access-objects

2) It looks like DAOTestExtension.Builder has a number of builder methods that allow you to set up database access properties for hibernate. https://github.com/dropwizard/dropwizard/blob/v2.0.12/dropwizard-testing/src/main/java/io/dropwizard/testing/common/DAOTest.java#L35

Can you give those suggestions a try and let me know if they work for you?

Dimas Guardado

unread,
Aug 23, 2020, 10:46:05 AM8/23/20
to dropwizard-user
For 2) I just noticed that dropwizard-example has some sample code demonstrating how to configure your DAO test to talk to a live database: https://github.com/dropwizard/dropwizard/blob/v2.0.12/dropwizard-example/src/test/java/com/example/helloworld/db/PersonDAOIntegrationTest.java#L35

Aditya Prasad

unread,
Aug 23, 2020, 6:52:06 PM8/23/20
to dropwiz...@googlegroups.com
Thanks very much Dimas. Your help is much appreciated!

1) That indeed worked! Thank you!

2) That looks like what I want, but I might not be doing it right. In my real server, after Hibernate is initialized, I call H2's RunScript to manually load the schema, and everything works fine. When I try the same thing in my tests (by loading the schema in a @BeforeEach method), H2 throws because some of the tables already exist. Do you know why there is a difference? I imagine that eventually I will want to remove my explicit schema, but right now it's nice to confirm that the one generated by Hibernate matches the one I already have.


--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-us...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dropwizard-user/72ad0ab3-399f-4dd8-8f80-2441b9c24de3n%40googlegroups.com.

Aditya Prasad

unread,
Aug 23, 2020, 8:07:41 PM8/23/20
to dropwiz...@googlegroups.com
Okay, I take back what I said earlier. In my server, my schema is explicitly loaded before Hibernate initializes it. This seems to work fine. In my tests, I can simply initialize Hibernate after setting up my schema (in the constructor). This way, if Hibernate makes any changes that are incompatible with my existing code, my test cases catch them.
Reply all
Reply to author
Forward
0 new messages