/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.util.persistencefn; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.entwinemedia.fn.Fn; import com.entwinemedia.fn.Unit; import com.entwinemedia.fn.data.Opt; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.persistence.EntityManager; public class PersistenceUtilTest { private PersistenceEnv penv; @Before public void before() { penv = PersistenceEnvs.mkTestEnv("test"); } @After public void after() { penv.close(); } @Test public void testPersistAndFind() { final long id = penv.tx(Queries.persist(TestDto.mk("key", "value"))).getId(); assertEquals("value", penv.tx(Queries.find(TestDto.class, id)).get().getValue()); } @Test public void testPersistOrUpdateUpdate() { assertTrue(penv.tx(TestDto.findAll).isEmpty()); final TestDto dto = penv.tx(Queries.persist(TestDto.mk("key", "value"))); assertEquals("value", penv.tx(Queries.find(TestDto.class, dto.getId())).get().getValue()); dto.setValue("new-value"); penv.tx(Queries.persistOrUpdate(dto)); assertEquals("new-value", penv.tx(Queries.find(TestDto.class, dto.getId())).get().getValue()); } @Test public void testPersistOrUpdatePersist() { assertTrue("The database should not contain any test entities", penv.tx(TestDto.findAll).isEmpty()); final TestDto dto = penv.tx(Queries.persistOrUpdate(TestDto.mk("key", "value"))); assertNotNull("The persisted entity should have an ID", penv.tx(Queries.getId(dto))); assertEquals("The persisted entity should be found by ID", "value", penv.tx(Queries.find(TestDto.class, dto.getId())).get().getValue()); dto.setValue("new-value"); penv.tx(Queries.persistOrUpdate(dto)); assertEquals("new-value", penv.tx(Queries.find(TestDto.class, dto.getId())).get().getValue()); } @Test public void testPersistOrUpdate() { assertTrue("The database should not contain any test entities", penv.tx(TestDto.findAll).isEmpty()); final TestDto dto = penv.tx(Queries.persistOrUpdate(TestDto.mk("key", "value"))); assertNotNull("The persisted entity should have an ID", dto.getId()); assertEquals("The generic ID getter should return the same value as the getId method on the entity", dto.getId(), penv.tx(Queries.getId(dto))); assertEquals("The persisted entity should be found by ID", "value", penv.tx(Queries.find(TestDto.class, dto.getId())).get().getValue()); final long generatedId = dto.getId() + 1; assertTrue("The generated ID should not be used already", penv.tx(Queries.find(TestDto.class, generatedId)).isNone()); penv.tx(Queries.persistOrUpdate(TestDto.mk(generatedId, "k", "v"))); assertEquals("The entity with the generated ID should be found", "v", penv.tx(Queries.find(TestDto.class, generatedId)).get().getValue()); } @Test public void testCloseEntityManager() { penv.tx(new Fn<EntityManager, Object>() { @Override public Object apply(EntityManager entityManager) { // this should not throw an exception in penv.tx() entityManager.close(); return null; } }); } @Test(expected = RuntimeException.class) public void testException() { penv.tx(new Fn<EntityManager, Object>() { @Override public Object apply(EntityManager entityManager) { throw new RuntimeException("error"); } }); } @Test public void testTransactionPropagation() { long id = penv.tx(new Fn<EntityManager, Long>() { @Override public Long apply(EntityManager em) { final TestDto dto = TestDto.mk("key", "A"); em.persist(dto); // nested transaction. if transaction propagation would fail a duplicate key exception would be thrown return save(dto); } }); assertEquals("dto value", "B", penv.tx(Queries.find(TestDto.class, id)).get().getValue()); } @Test public void testRemove() { final TestDto dto = TestDto.mk("key", "value"); assertNull("New entity should not have an ID", dto.getId()); final TestDto persistedDto = penv.tx(Queries.persist(dto)); assertNotNull("Persisted entity should have an ID", persistedDto.getId()); assertEquals("Persisting an entity modifies it", dto, persistedDto); final Opt<TestDto> fetchedDto = penv.tx(Queries.find(TestDto.class, dto.getId())); assertTrue("The entity should be found by ID", fetchedDto.isSome()); assertNotEquals("The fetched entity should not be the same object as the persisted one", dto, fetchedDto.get()); assertFalse("The fetched entity should be in detached state", penv.tx(Queries.contains(fetchedDto.get()))); assertEquals("The entity should be removed even though it is in detached state", Unit.unit, penv.tx(Queries.remove(fetchedDto.get()))); assertTrue("The entity should be removed now", penv.tx(Queries.find(TestDto.class, dto.getId())).isNone()); } private long save(TestDto dto) { dto.setValue("B"); return penv.tx(Queries.persist(dto)).getId(); } }