/* * Copyright 2004-2009 the original author or authors. * * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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.compass.sample.petclinic; import java.util.Collection; import java.util.Date; import javax.sql.DataSource; import junit.framework.TestCase; import org.compass.core.Compass; import org.compass.core.CompassCallbackWithoutResult; import org.compass.core.CompassDetachedHits; import org.compass.core.CompassException; import org.compass.core.CompassHits; import org.compass.core.CompassSession; import org.compass.core.CompassTemplate; import org.compass.gps.ActiveMirrorGpsDevice; import org.compass.gps.CompassGps; import org.compass.gps.CompassGpsDevice; import org.compass.sample.petclinic.util.EntityUtils; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; /** * Base class for Clinic tests. Allows subclasses to specify context locations. * <p/> * This class extends AbstractTransactionalDataSourceSpringContextTests, one of * the valuable test superclasses provided in the org.springframework.test * package. This represents best practice for integration tests with Spring. The * AbstractTransactionalDataSourceSpringContextTests superclass provides the * following services: * <li>Injects test dependencies, meaning that we don't need to perform * application context lookups. See the setClinic() method. Injection uses * autowiring by type. * <li>Executes each test method in its own transaction, which is automatically * rolled back by default. This means that even if tests insert or otherwise * change database state, there is no need for a teardown or cleanup script. * <li>Provides useful inherited protected fields, such as a JdbcTemplate that * can be used to verify database state after test operations, or verify the * results of queries performed by application code. An ApplicationContext is * also inherited, and can be used for explicit lookup if necessary. * <p/> * The AbstractTransactionalDataSourceSpringContextTests and related classes are * shipped in the spring-mock.jar. * * @author Ken Krebs * @author Rod Johnson * @see org.springframework.test.AbstractTransactionalDataSourceSpringContextTests */ public abstract class AbstractClinicTests extends TestCase { private ConfigurableApplicationContext applicationContext; private JdbcTemplate jdbcTemplate; private TransactionTemplate transactionTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } protected Clinic clinic; /** * This method is provided to set the Clinic instance being tested by the * Dependency Injection injection behaviour of the superclass from the * org.springframework.test package. * * @param clinic clinic to test */ public void setClinic(Clinic clinic) { this.clinic = clinic; } // <!-- COMPASS START // Makes the tests run without a running HSQL instance protected CompassGps compassGps; protected CompassGpsDevice compassGpsDevice; protected CompassTemplate compassTemplate; protected Compass compass; public void setCompassGps(CompassGps compassGps) { this.compassGps = compassGps; // use read commited transaction isolation since we are performing the // index operation and testing within the same transaction //((SingleCompassGps) compassGps).setIndexTransactionIsolation(TransactionIsolation.READ_COMMITTED); } public void setCompass(Compass compass) { this.compass = compass; this.compassTemplate = new CompassTemplate(compass); } public void setCompassGpsDevice(CompassGpsDevice compassGpsDevice) { this.compassGpsDevice = compassGpsDevice; } public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionTemplate = new TransactionTemplate(transactionManager); } protected abstract boolean hasClassMappings(); protected abstract String[] getConfigLocations(); /** * If the gps device is active mirror type, perform the mirroring */ protected void doPerformMirroringIfNeeded() { if (compassGpsDevice instanceof ActiveMirrorGpsDevice) { ((ActiveMirrorGpsDevice) compassGpsDevice).performMirroring(); } } protected void setUp() throws Exception { this.applicationContext = new ClassPathXmlApplicationContext(getConfigLocations()); this.applicationContext.getBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); } protected void tearDown() throws Exception { this.applicationContext.close(); } private void performIndex() { compassGps.index(); } // COMPASS END --> public void testGetVets() { transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { Collection vets = clinic.getVets(); // Use the inherited JdbcTemplate (from // AbstractTransactionalDataSourceSpringContextTests) // to verify the results of the query assertEquals("JDBC query must show the same number of vets", jdbcTemplate .queryForInt("SELECT COUNT(0) FROM VETS"), vets.size()); Vet v1 = (Vet) EntityUtils.getById(vets, Vet.class, 2); assertEquals("Leary", v1.getLastName()); assertEquals(1, v1.getNrOfSpecialties()); assertEquals("radiology", ((Specialty) v1.getSpecialties().get(0)).getName()); Vet v2 = (Vet) EntityUtils.getById(vets, Vet.class, 3); assertEquals("Douglas", v2.getLastName()); assertEquals(2, v2.getNrOfSpecialties()); assertEquals("dentistry", ((Specialty) v2.getSpecialties().get(0)).getName()); assertEquals("surgery", ((Specialty) v2.getSpecialties().get(1)).getName()); } }); } public void testGetPetTypes() { transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { Collection petTypes = clinic.getPetTypes(); assertEquals("JDBC query must show the same number of pet typess", jdbcTemplate .queryForInt("SELECT COUNT(0) FROM TYPES"), petTypes.size()); PetType t1 = (PetType) EntityUtils.getById(petTypes, PetType.class, 1); assertEquals("cat", t1.getName()); PetType t4 = (PetType) EntityUtils.getById(petTypes, PetType.class, 4); assertEquals("snake", t4.getName()); } }); } public void testFindOwners() { Collection owners = this.clinic.findOwners("Davis"); assertEquals(2, owners.size()); owners = this.clinic.findOwners("Daviss"); assertEquals(0, owners.size()); } public void testLoadOwner() { Owner o1 = this.clinic.loadOwner(1); assertTrue(o1.getLastName().startsWith("Franklin")); Owner o10 = this.clinic.loadOwner(10); assertEquals("Carlos", o10.getFirstName()); } public void testInsertOwner() { Collection owners = this.clinic.findOwners("Schultz"); int found = owners.size(); Owner owner = new Owner(); owner.setLastName("Schultz"); this.clinic.storeOwner(owner); owners = this.clinic.findOwners("Schultz"); assertEquals(found + 1, owners.size()); } public void testUpdateOwner() throws Exception { transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { Owner o1 = clinic.loadOwner(1); String old = o1.getLastName(); o1.setLastName(old + "X"); clinic.storeOwner(o1); o1 = clinic.loadOwner(1); assertEquals(old + "X", o1.getLastName()); } }); } public void testLoadPet() { Collection types = this.clinic.getPetTypes(); Pet p7 = this.clinic.loadPet(7); assertTrue(p7.getName().startsWith("Samantha")); assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId()); assertEquals("Jean", p7.getOwner().getFirstName()); Pet p6 = this.clinic.loadPet(6); assertEquals("George", p6.getName()); assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId()); assertEquals("Peter", p6.getOwner().getFirstName()); } public void testInsertPet() { Owner o6 = this.clinic.loadOwner(6); int found = o6.getPets().size(); Pet pet = new Pet(); pet.setName("bowser"); o6.addPet(pet); Collection types = this.clinic.getPetTypes(); pet.setType((PetType) EntityUtils.getById(types, PetType.class, 2)); pet.setBirthDate(new Date()); assertEquals(found + 1, o6.getPets().size()); this.clinic.storePet(pet); o6 = this.clinic.loadOwner(6); assertEquals(found + 1, o6.getPets().size()); } public void testUpdatePet() throws Exception { Pet p7 = this.clinic.loadPet(7); String old = p7.getName(); p7.setName(old + "X"); this.clinic.storePet(p7); p7 = this.clinic.loadPet(7); assertEquals(old + "X", p7.getName()); } public void testInsertVisit() { Pet p7 = this.clinic.loadPet(7); int found = p7.getVisits().size(); Visit visit = new Visit(); p7.addVisit(visit); visit.setDescription("test"); this.clinic.storeVisit(visit); assertEquals(found + 1, p7.getVisits().size()); } public void testCompassReindex() { // reindex the database performIndex(); // use sporadic data to test that we reindexed the db compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("Harold"); assertEquals(1, hits.getLength()); assertEquals("Harold", hits.resource(0).get(Petclinic.MetaData.FirstName.Name)); if (hasClassMappings()) { Owner owner = (Owner) hits.data(0); assertEquals("Harold", owner.getFirstName()); assertEquals(1, owner.getPets().size()); Pet pet = (Pet) owner.getPets().get(0); assertEquals("Iggy", pet.getName()); } } }); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("Leo"); assertEquals(1, hits.getLength()); assertEquals("Leo", hits.resource(0).get(Petclinic.MetaData.Name.Name)); if (hasClassMappings()) { Pet pet = (Pet) hits.data(0); assertEquals("Leo", pet.getName()); assertEquals("George", pet.getOwner().getFirstName()); } } }); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("James"); assertEquals(1, hits.getLength()); assertEquals("James", hits.resource(0).get(Petclinic.MetaData.FirstName.Name)); if (hasClassMappings()) { Vet vet = (Vet) hits.data(0); assertEquals("James", vet.getFirstName()); } } }); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { if (hasClassMappings()) { Pet samantha = (Pet) session.load(Pet.class, new Integer(7)); assertEquals(2, samantha.getVisits().size()); } } }); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("George"); assertEquals(2, hits.getLength()); if (hasClassMappings()) { hits = session.find("radiology"); assertEquals(2, hits.length()); } } }); } public void testInsertOwnerCompassMirror() { // reindex the database performIndex(); // test that Schultz is not in compass compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("Schultz"); assertEquals(0, hits.getLength()); } }); // do the orig spring test Collection owners = this.clinic.findOwners("Schultz"); int found = owners.size(); Owner owner = new Owner(); owner.setLastName("Schultz"); this.clinic.storeOwner(owner); owners = this.clinic.findOwners("Schultz"); assertEquals(found + 1, owners.size()); // test that Schultz is in compass as well doPerformMirroringIfNeeded(); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("Schultz"); assertEquals(1, hits.getLength()); assertEquals("Schultz", hits.resource(0).get(Petclinic.MetaData.LastName.Name)); if (hasClassMappings()) { Owner owner = (Owner) hits.data(0); assertEquals("Schultz", owner.getLastName()); } } }); } public void testUpdateOwnerCompassMirror() throws Exception { // reindex the database performIndex(); Owner o1 = this.clinic.loadOwner(1); String old = o1.getLastName(); if (hasClassMappings()) { // load the owner using compass Owner oldCompassOwner = (Owner) compassTemplate.load(Owner.class, new Integer(1)); // validate that it is the same as the db assertEquals(old, oldCompassOwner.getLastName()); } CompassDetachedHits hits = compassTemplate.findWithDetach(old + "X"); assertEquals(0, hits.getLength()); // update and check db o1.setLastName(old + "X"); this.clinic.storeOwner(o1); // we need to cause the ORM tool to flush it's data // which it won't if we call the loadOwner method // most ORM will flush as a result of a query on // the object // Note, that we do it since we want to test the change // WITHIN the same transaction, usually, we won't check // compass within the current transaction this.clinic.findOwners("Test"); o1 = this.clinic.loadOwner(1); assertEquals(old + "X", o1.getLastName()); // check with compass doPerformMirroringIfNeeded(); hits = compassTemplate.findWithDetach(old + "X"); assertEquals(1, hits.getLength()); if (hasClassMappings()) { Owner newCompassOwner = (Owner) compassTemplate.load(Owner.class, new Integer(1)); assertEquals(old + "X", newCompassOwner.getLastName()); } } public void testInsertPetCompassMirror() { // reindex the database performIndex(); // test that browser is not in compass compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("bowser"); assertEquals(0, hits.getLength()); } }); Owner o6 = this.clinic.loadOwner(6); int found = o6.getPets().size(); Pet pet = new Pet(); pet.setName("bowser"); o6.addPet(pet); Collection types = this.clinic.getPetTypes(); pet.setType((PetType) EntityUtils.getById(types, PetType.class, 2)); pet.setBirthDate(new Date()); assertEquals(found + 1, o6.getPets().size()); this.clinic.storePet(pet); o6 = this.clinic.loadOwner(6); assertEquals(found + 1, o6.getPets().size()); // test that bowser is in compass as well doPerformMirroringIfNeeded(); compassTemplate.execute(new CompassCallbackWithoutResult() { protected void doInCompassWithoutResult(CompassSession session) throws CompassException { CompassHits hits = session.find("bowser"); assertEquals(1, hits.getLength()); assertEquals("bowser", hits.resource(0).get(Petclinic.MetaData.Name.Name)); if (hasClassMappings()) { Pet pet = (Pet) hits.data(0); assertEquals("bowser", pet.getName()); } } }); } public void testUpdatePetCompassMirror() throws Exception { // reindex the database performIndex(); Pet p7 = this.clinic.loadPet(7); String old = p7.getName(); // load the old pet if (hasClassMappings()) { Pet oldPet = (Pet) compassTemplate.load(Pet.class, new Integer(7)); // check the same assertEquals(old, oldPet.getName()); } CompassDetachedHits hits = compassTemplate.findWithDetach(old + "X"); assertEquals(0, hits.getLength()); p7.setName(old + "X"); this.clinic.storePet(p7); p7 = this.clinic.loadPet(7); assertEquals(old + "X", p7.getName()); // flush the database this.clinic.getPets(); // check the updae in compass doPerformMirroringIfNeeded(); if (hasClassMappings()) { Pet newPet = (Pet) compassTemplate.load(Pet.class, new Integer(7)); assertEquals(old + "X", newPet.getName()); hits = compassTemplate.findWithDetach(old + "X"); assertEquals(1, hits.getLength()); // one pet (visits are accessed // using OSEM) } else { hits = compassTemplate.findWithDetach(old + "X"); assertEquals(3, hits.getLength()); // one pet and two visits } } }