views:

29

answers:

2

I am in the process of unit testing a DAO built with Spring/JPA and Hibernate as the provider.

Prior to running the test, DBUnit inserted a User record with username "poweruser" -- username is the primary key in the users table. Here is the integration test method:

@Test
@ExpectedException(EntityExistsException.class)
public void save_UserTestDataSaveUserWithPreExistingId_EntityExistsException() {
    User newUser = new UserImpl("poweruser");

    newUser.setEmail("[email protected]");
    newUser.setFirstName("New");
    newUser.setLastName("User");
    newUser.setPassword("secret");

    dao.persist(newUser);
}

I have verified that the record is in the database at the start of this method. Not sure if this is relevant, but if I do a dao.flush() at the end of this method I get the following exception:

javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: 
    Could not execute JDBC batch update
+1  A: 

Apparently unless flush is called explicitly or implicitly (via a query or a commit) then any potential exception will not be thrown. So I guess I am going to have to call flush() in all of my integration tests that modify data.

HDave
Look at http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/Session.html#setFlushMode(org.hibernate.FlushMode)
Jherico
Its good stuff, but it still doesn't talk about *when* a persistence exception is thrown...e.g. during persist() or during flush(). I just think its a little weird that I have to call flush() in all my integration tests...is this normal?
HDave
+1  A: 

I assume you're using the transactional integration tests? These tests rollback at the end of each test method, so you are indeed missing the flush.

I don't know if this is useful, but if you were autogenerating the ID, then a flush would happen at the persist() because a trip to the database is needed to get the generated ID. But if you're assigning your own ID's, then the flush is delayed until the commit, as you've seen.

Dick Chesterwood
I am using the transactional integration tests. Great point, I hadn't thought of the autogenerated key. However my entire app uses application assigned UUIDs as surrogate primary key. So flush() is my new friend....
HDave