package book.example.persistence.tests;
import book.example.persistence.tests.builders.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import java.util.Arrays;
import java.util.List;
import static book.example.persistence.tests.PersistenceReflection.assertHaveSamePersistentFields;
import static book.example.persistence.tests.PersistenceReflection.idOf;
import static org.junit.Assert.assertNotNull;
public class PersistabilityTest {
final EntityManagerFactory factory = Persistence.createEntityManagerFactory("example");
final EntityManager entityManager = factory.createEntityManager();
final JPATransactor transactor = new JPATransactor(entityManager);
@Before
public void cleanDatabase() throws Exception {
new DatabaseCleaner(entityManager).clean();
}
@After
public void tearDown() {
entityManager.close();
factory.close();
}
@SuppressWarnings("unchecked")
final List<? extends Builder<?>> persistentObjectBuilders = Arrays.asList(
new AddressBuilder(),
new PayMateDetailsBuilder(),
new CreditCardDetailsBuilder(),
new AuctionSiteBuilder(),
new AuctionSiteLoginBuilder().forSite(persisted(new AuctionSiteBuilder())),
new CustomerBuilder()
.usingAuctionSites(
new AuctionSiteLoginBuilder().forSite(persisted(new AuctionSiteBuilder())))
.withPaymentMethods(
new CreditCardDetailsBuilder(),
new PayMateDetailsBuilder()));
@Test
public void canRoundTripPersistentObjects() throws Exception {
for (Builder<?> builder : persistentObjectBuilders) {
assertCanBePersisted(builder);
}
}
private void assertCanBePersisted(Builder<?> builder) throws Exception {
try {
assertReloadsWithSameStateAs(persistedObjectFrom(builder));
}
catch (PersistenceException e) {
throw new PersistenceException("could not round-trip " + typeFor(builder), e);
}
}
private String typeFor(Builder<?> builder) {
return builder.getClass().getSimpleName().replace("Builder", "");
}
private Object persistedObjectFrom(final Builder<?> builder) throws Exception {
return transactor.performQuery(new QueryUnitOfWork<Object>() {
public Object query() throws Exception {
// Build the saved object in the transaction so any sub-builders can do database activity if necessary
Object saved = builder.build();
entityManager.persist(saved);
return saved;
}
});
}
private void assertReloadsWithSameStateAs(final Object original) throws Exception {
transactor.perform(new UnitOfWork() {
public void work() throws Exception {
Object loaded = entityManager.find(original.getClass(), idOf(original));
assertNotNull("should have found saved " + original.getClass().getSimpleName(), loaded);
assertHaveSamePersistentFields(loaded, original);
}
});
}
private <T> Builder<T> persisted(final Builder<T> builder) {
return new Builder<T>() {
public T build() {
T entity = builder.build();
entityManager.persist(entity);
return entity;
}
};
}
}