package br.com.caelum.calopsita.infra;
import static org.junit.Assert.assertFalse;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
import br.com.caelum.calopsita.controller.HomeController;
import br.com.caelum.calopsita.infra.interceptor.HibernateInterceptor;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.resource.DefaultResourceClass;
import br.com.caelum.vraptor.resource.DefaultResourceMethod;
import br.com.caelum.vraptor.resource.ResourceMethod;
public class HibernateInterceptorTest {
private Mockery mockery;
private HibernateInterceptor interceptor;
private InterceptorStack stack;
private Session session;
@Before
public void setUp() throws Exception {
mockery = new Mockery();
stack = mockery.mock(InterceptorStack.class);
session = mockery.mock(Session.class);
interceptor = new HibernateInterceptor(session);
}
@Test
public void openAndCloseTransactionWhenFlowIsSuccessful() throws Exception {
givenThatFlowWasSuccessful();
Transaction t = shouldBeginATransaction(session);
shouldCommitTheTransaction(t);
whenInterceptOccurs();
mockery.assertIsSatisfied();
}
@Test(expected=InterceptionException.class)
public void rollbackTransactionWhenFlowFails() throws Exception {
givenThatFlowThrowsAException();
Transaction t = shouldBeginATransaction(session);
shouldRollbackTheTransaction(t);
whenInterceptOccurs();
mockery.assertIsSatisfied();
}
@Test
public void shouldBypassUsersAndHomeController() throws Exception {
assertFalse(interceptor.accepts(anyResourceMethodOf(HomeController.class)));
}
private ResourceMethod anyResourceMethodOf(Class<?> clazz) {
return new DefaultResourceMethod(new DefaultResourceClass(clazz), clazz.getDeclaredMethods()[0]);
}
private void shouldRollbackTheTransaction(final Transaction t) {
mockery.checking(new Expectations() {
{
one(t).isActive();
will(returnValue(true));
one(t).rollback();
}
});
}
private void givenThatFlowThrowsAException() {
mockery.checking(new Expectations() {
{
one(stack).next(with(any(ResourceMethod.class)), with(any(Object.class)));
will(throwException(new InterceptionException("")));
}
});
}
private void shouldCommitTheTransaction(final Transaction t) {
mockery.checking(new Expectations() {
{
one(t).commit();
}
});
}
private Transaction shouldBeginATransaction(final Session session) {
final Transaction transaction = mockery.mock(Transaction.class);
mockery.checking(new Expectations() {
{
one(session).beginTransaction();
will(returnValue(transaction));
allowing(session).getTransaction();
will(returnValue(transaction));
}
});
return transaction;
}
private void givenThatFlowWasSuccessful() {
mockery.checking(new Expectations() {
{
one(stack).next(with(any(ResourceMethod.class)), with(any(Object.class)));
}
});
}
private void whenInterceptOccurs() {
interceptor.intercept(stack, null, null);
}
}