package org.testfun.jee;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.testfun.jee.runner.PersistenceXml;
import org.testfun.jee.runner.SingletonDataSource;
import static org.hamcrest.CoreMatchers.*;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.sql.*;
import java.util.List;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*;
@RunWith(EjbWithMockitoRunner.class)
public class EjbWithMockitoRunnerTransactionTest {
private static boolean rowAdded;
@PersistenceContext
private EntityManager entityManager;
@Rule
public ExpectedException thrown = ExpectedException.none();
@BeforeClass
public static void createTables() throws SQLException {
dropTables();
try (
Connection connection = DriverManager.getConnection(PersistenceXml.getInstnace().getConnectionUrl());
Statement statement = connection.createStatement()
) {
statement.execute("CREATE TABLE duplicates (id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name VARCHAR(50) NOT NULL UNIQUE)");
}
rowAdded = false;
}
@AfterClass
public static void dropTables() throws SQLException {
// Must rollback the connection used by the entity manager in order to avoid locks due to inserts done before (recall transactions are never committed).
SingletonDataSource.getDataSource().getConnection().rollback();
try (
Connection connection = DriverManager.getConnection(PersistenceXml.getInstnace().getConnectionUrl());
Statement statement = connection.createStatement()
) {
statement.execute("DROP TABLE IF EXISTS duplicates");
}
}
@Test
public void test1() {
firstAddRowNextVerify();
}
@Test
public void test2() {
firstAddRowNextVerify();
}
@Test
public void dbThrowDuplicateKey() {
entityManager.persist(new Duplicates("kuki"));
try {
entityManager.persist(new Duplicates("kuki"));
} catch (Throwable t) {
assertThat(ExceptionUtils.getRootCauseMessage(t), containsString("unique constraint or index violation"));
}
}
@Test
public void preUpdate() {
Duplicates entity = new Duplicates("kuki");
entityManager.persist(entity);
assertNull(entity.getDuplicateName());
entity.setName("puki");
entityManager.flush();
assertEquals(entity.getName(), entity.getDuplicateName());
}
/**
* This method is used for testing that a transaction is rolled back at the end of a test.
* Because the rollback occurs after all @After methods are invoked, the test cannot be done using @After.
* Also, there are no guarantees as for the order test methods are called.
* This method solves the problem by performing "insert" on the first time it is called and "verify" on the second
* time.
*/
private void firstAddRowNextVerify() {
if (rowAdded) {
// If a row was already added by a previous run, verify it was rolled back.
List rows = entityManager.createQuery("FROM Duplicates AS dups").getResultList();
assertEquals(0, rows.size());
}
else {
// If no row was added so far (its the first call to this method) than add a row.
Duplicates row = new Duplicates("kuki");
entityManager.persist(row);
assertThat(row.getId(), not(0));
assertSame(row, entityManager.find(Duplicates.class, row.getId()));
rowAdded = true;
}
}
}