Given your recommendation that using HibernateSessionManager in unit tests is not appropriate, and Howard's little hint about constructor- based injection, I was able to come up with an acceptable strategy, whereby I create the sessionfactory and the session for my unit tests, and pass that session to each of my services. This means I don't need to create the registry anymore, which is fine, because I'm not testing the registry (nor HSM, for that matter).

    @BeforeClass
    protected void setup() {
AnnotationConfiguration configuration = new AnnotationConfiguration();
        configuration.addAnnotatedClass(User.class);
SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
        session = sessionFactory.openSession();

        userService = new UserServiceImpl(session);

    }

Thanks,

J


On Mar 18, 2008, at 5:05 PM, Josh Canfield wrote:

You need to call session.flush after you save, this will send your
data to the database and trigger any constraint exceptions.
http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#flush()

I'm pretty sure that the tapestry-hibernate thread/request management
is done within the context of a request and you will need to plumb
that yourself, perhaps in @Before and @After methods. I can't look it
up now, but if I think about it later I'll track it down.

I wouldn't recommend this approach though. In your tests you should
want to have more control over what is happening with your objects.
For instance, letting tapestry-hibernate take care of the flush/commit
of the session/transaction means that you can't write tests like your
second one because it wouldn't throw an exception until
tapestry-hibernate cleanup happend after the method has exited.

Josh

On Tue, Mar 18, 2008 at 10:54 AM, Julian Wood <[EMAIL PROTECTED]> wrote:
I have a UserService:

public class UserServiceImpl implements UserService {
   private Session session;

   public UserServiceImpl(@InjectService("Session")Session session) {
       this.session = session;
   }

   public void save(User user) {
       session.save(user);
   }
}

I bind this in the AppModule, and then I can use it in any page or
component class. This is great.

Now for unit testing my UserService, I make my own RegistryBuilder as
others have recommended, and can do a test:

   @BeforeClass
   protected void setup() {
       RegistryBuilder builder = new RegistryBuilder();

       builder.add(HibernateModule.class);
       builder.add(SetupForTest.class);
       builder.add(AppModule.class);

       Registry registry = builder.build();

       registry.performRegistryStartup();

       userService = registry.getService("userService",
UserService.class);

   }

   @Test
   public void testAddUsers() throws Exception {

       User user = createRandomUser();
       userService.save(user);

       List<User> users = userService.getUsers();
       assertEquals(1, users.size());
   }

Now, the first problem is that this will not be committed to the
database, when you have hibernate configured with autocommit=false. To
accomplish that, I need to grab the session out of the registry and
add this:

   @AfterClass
   protected void closeSession() throws Exception {
       session.getTransaction().commit();
       session.close();
   }

I would have thought that Tapestry-hibernate would take care of that
(it does when run as a webapp, so no real problem here), given it is
supposed to commit or rollback when the thread ends (in this case the
thread is running all the tests).

My real question comes when I want to test some of the constraints on
my database. For instance, there is a unique constraint on the
username in the User class. So a test might be:

   @Test
   public void testAddUsersWithSameUsernames() throws Exception {

       User user = createRandomUser("woodj");
       userService.save(user);

       User duplicateUser = createRandomUser("woodj");
       try {
           userService.save(duplicateUser);

           Assert.fail("Should have thrown exception with duplicate
username constraint exception.");
       } catch (HibernateException e) {
           //success
       }
  }

Now when this test is run I get a failure (don't flush the Session
after an exception occurs), because of my closeSession method. I can
remove the closeSession, which shouldn't really be there anyway, and
everything passes, but I don't get the additional comfort of checking
my db to make sure hibernate synched things up properly.

I can rollback manually in the exception, by getting the current txn
from the session service, but I get the same failure. It seems that no matter what you do, once an exception is thrown, and regardless of how
you handle it, that session is done.

I've also tried all the aforementioned, but using the
HibernateSessionManager service to grab the session, which should
allow me to commit and abort midsession, but it suffers the exact same
failures, despite it's assurance in the javadoc:

Manages the Hibernate session for the current thread. This includes
creating the session as
needed, allowing the session to checkpoint (commit the current
transaction and continue) and
commit the transaction automatically at the end of the request.

So my question is: can I test my services, under the
HibernateSessionManager, and have the flexibility to commit and
rollback midsession? It seems not, but maybe I missed something.

And just BTW, if I create my own SessionFactory and handle the session
and txn's myself, everything works as expected.

Thanks for any thoughts.

J


On Feb 4, 2008, at 8:01 AM, Davor Hrg wrote:

HibernateSessionManager handles session for a request,
and does commit at the end.

if you want to have more than one commit you should not call it
directly on the injected session since it will confuse
HibernateSessionManager.
Same goes for rollback.

Davor Hrg


On Feb 4, 2008 3:52 PM, Angelo Chen <[EMAIL PROTECTED]>
wrote:

hi,

I have used Session session in my app and it works, I have seen
HibernateSessionManager being mentioned many times in the list,
what are the
advantages of using HibernateSessionManager compared app which does
not
explicitly use it?

Thanks,

Angelo
--
View this message in context: 
http://www.nabble.com/T5%3A-HibernateSessionManager-tp15268872p15268872.html
Sent from the Tapestry - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]





--
--
TheDailyTube.com. Sign up and get the best new videos on the internet
delivered fresh to your inbox.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to