package book.example.persistence.tests; import book.example.common.exceptions.Defect; import book.example.persistence.jpa.PersistentCustomerBase; import book.example.persistence.model.Customer; import book.example.persistence.tests.builders.CustomerBuilder; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; 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 java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import static book.example.persistence.tests.builders.CreditCardDetailsBuilder.aCreditCard; import static book.example.persistence.tests.builders.CustomerBuilder.aCustomer; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.Assert.assertThat; public class PersistentCustomerBaseTest { final EntityManagerFactory factory = Persistence.createEntityManagerFactory("example"); final EntityManager entityManager = factory.createEntityManager(); final JPATransactor transactor = new JPATransactor(entityManager); final PersistentCustomerBase customerBase = new PersistentCustomerBase(entityManager); @Before public void cleanDatabase() throws Exception { new DatabaseCleaner(entityManager).clean(); } @After public void tearDown() { entityManager.close(); factory.close(); } @SuppressWarnings("unchecked") @Test public void findsCustomersWithCreditCardsThatAreAboutToExpire() throws Exception { final String deadline = "6 Jun 2009"; addCustomers( aCustomer().withName("Alice (Expired)") .withPaymentMethods(aCreditCard().withExpiryDate(date("1 Jan 2009"))), aCustomer().withName("Bob (Expired)") .withPaymentMethods(aCreditCard().withExpiryDate(date("5 Jun 2009"))), aCustomer().withName("Carol (Valid)") .withPaymentMethods(aCreditCard().withExpiryDate(date(deadline))), aCustomer().withName("Dave (Valid)") .withPaymentMethods(aCreditCard().withExpiryDate(date("7 Jun 2009"))) ); assertCustomersExpiringOn(date(deadline), containsCustomersNamed("Alice (Expired)", "Bob (Expired)")); } // Needed to work around Java type inference not working for parameters private Matcher<Iterable<Customer>> containsCustomersNamed(String name1, String name2) { return containsInAnyOrder(customerNamed(name1), customerNamed(name2)); } private void addCustomers(final CustomerBuilder... customers) throws Exception { transactor.perform(new UnitOfWork() { public void work() throws Exception { for (CustomerBuilder customer : customers) { customerBase.addCustomer(customer.build()); } } }); } private void assertCustomersExpiringOn(final Date date, final Matcher<Iterable<Customer>> matcher) throws Exception { transactor.perform(new UnitOfWork() { public void work() throws Exception { assertThat(customerBase.customersWithExpiredCreditCardsAsOf(date), matcher); } }); } protected Matcher<Customer> customerNamed(final String name) { return new TypeSafeMatcher<Customer>() { @Override protected boolean matchesSafely(Customer customer) { return customer.name().equals(name); } public void describeTo(Description description) { description.appendText("a customer named ").appendValue(name); } @Override protected void describeMismatchSafely(Customer customer, Description description) { description.appendText("name was ").appendValue(customer.name()); } }; } private DateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy"); private Date date(String text) { try { return dateFormat.parse(text); } catch (ParseException e) { throw new Defect("invalid date syntax", e); } } }