package no.brodwall.insanejava.rest; import java.io.Serializable; import java.util.Random; import static no.brodwall.insanejava.rest.utils.AssertionUtils.*; import net.sf.cglib.proxy.Factory; import net.sf.cglib.proxy.LazyLoader; import no.brodwall.insanejava.rest.utils.ObjectUtils; import junit.framework.TestCase; public abstract class RepositoryTest extends TestCase { private Object insertedObject; private Serializable key; protected abstract Repository getRepository(); @Override protected final void setUp() throws Exception { insertedObject = createDistinctObject(); key = getRepository().insert(insertedObject); getRepository().writeChanges(); } public void testRetrieve() { Object retrievedObject = getRepository().retrieve(key); assertNotSame("retrieve in new session should not return same", insertedObject, retrievedObject); assertEquals(insertedObject, retrievedObject); assertAllFieldsEquals(insertedObject, retrievedObject); assertSame("All retrieves in session should return same instance", retrievedObject, getRepository().retrieve(key)); } public void testUpdate() { Object updatedObject = getRepository().retrieve(key); changeObject(updatedObject); assertFalse(insertedObject + " should differ from " + updatedObject, insertedObject.equals(updatedObject)); getRepository().update(key, updatedObject); getRepository().writeChanges(); assertEquals(updatedObject, getRepository().retrieve(key)); } public void testDelete() { getRepository().delete(key); getRepository().writeChanges(); assertDeleted(getRepository().retrieve(key)); } public void testGetKey() { Object retrievedObject = getRepository().retrieve(key); Serializable repoKey = getRepository().getKey(retrievedObject); assertEquals(key, repoKey); } public void testUpdateNonExisting() { Long nonexistingKey = Math.abs(new Random().nextLong()); Object updatedObject = createDistinctObject(); try { getRepository().update(nonexistingKey, updatedObject); fail("Trying to update nonexisting object " + nonexistingKey + " should result in exception"); } catch (RuntimeException e) { assertStringContains(nonexistingKey.toString(), e.getMessage()); } } public void testUpdateDeleteWillDelete() { Object updatedObject = getRepository().retrieve(key); changeObject(updatedObject); getRepository().update(key, updatedObject); getRepository().delete(key); getRepository().update(key, updatedObject); getRepository().writeChanges(); assertDeleted(getRepository().retrieve(key)); } public void testDiscardedInsert() { Serializable key2 = getRepository().insert(createDistinctObject()); getRepository().discardChanges(); assertDeleted(getRepository().retrieve(key2)); } public void testDiscardedUpdate() { Object updatedObject = getRepository().retrieve(key); assertNotSame(insertedObject, updatedObject); changeObject(updatedObject); assertFalse(insertedObject.equals(updatedObject)); getRepository().discardChanges(); assertEquals(insertedObject, getRepository().retrieve(key)); } public void testDiscardedDelete() { getRepository().delete(key); getRepository().discardChanges(); assertEquals(insertedObject, getRepository().retrieve(key)); getRepository().writeChanges(); assertEquals(insertedObject, getRepository().retrieve(key)); } protected void assertDeleted(Object o) { if (o == null) { return; } if (o instanceof Factory) { for (Object callback : ((Factory)o).getCallbacks()) { if (callback instanceof LazyLoader) { try { assertNull(((LazyLoader)callback).loadObject()); return; } catch (Exception e) { throw new RuntimeException(e); } } } } assertNull(o); } /** Every call to this method should return an object that is not equals any * previous object returned from createDistinctObject */ protected abstract Object createDistinctObject(); /** A clone of the updatedObject should never be equal the updated * object after this method is called. */ protected abstract void changeObject(Object updatedObject); /** Verifies that subclasses behave reasonably */ public void testInvariants() { assertFalse("createDistinct should always return distinct objects", createDistinctObject().equals(createDistinctObject())); Object t = createDistinctObject(); Object clone = ObjectUtils.clone(t); changeObject(t); assertFalse(clone.equals(t)); } /** Verifies that hashCode and equals properties of the entity behave reasobably during storage. */ public void testHashCodeEquals() { Object object = createDistinctObject(); int preSaveHashCode = object.hashCode(); Serializable key2 = getRepository().insert(object); assertEquals("saving should not change hashCode", preSaveHashCode, object.hashCode()); getRepository().writeChanges(); Object retrievedObject = getRepository().retrieve(key2); assertNotSame(retrievedObject, object); assertEquals(retrievedObject, object); assertEquals(retrievedObject.hashCode(), object.hashCode()); } }