/*
* Copyright 2008, Unitils.org
*
* 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.unitils.reflectionassert.hibernate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.SessionFactory;
import org.junit.After;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.unitils.UnitilsJUnit4;
import org.unitils.core.ConfigurationLoader;
import org.unitils.core.Unitils;
import static org.unitils.database.SQLUnitils.executeUpdate;
import static org.unitils.database.SQLUnitils.executeUpdateQuietly;
import org.unitils.database.DatabaseModule;
import org.unitils.database.annotations.Transactional;
import static org.unitils.database.util.TransactionMode.COMMIT;
import static org.unitils.dbmaintainer.util.DatabaseModuleConfigUtils.PROPKEY_DATABASE_DIALECT;
import org.unitils.orm.hibernate.annotation.HibernateSessionFactory;
import org.unitils.reflectionassert.ReflectionAssert;
import org.unitils.reflectionassert.ReflectionComparator;
import static org.unitils.reflectionassert.ReflectionComparatorFactory.createRefectionComparator;
import org.unitils.reflectionassert.difference.Difference;
import org.unitils.util.PropertyUtils;
import javax.sql.DataSource;
import static java.util.Arrays.asList;
import java.util.Properties;
/**
* Test class for Hibernate proxy related tests of the {@link ReflectionComparator} .
* <p/>
* Currently this is only implemented for HsqlDb.
*
* @author Tim Ducheyne
* @author Filip Neven
*/
@Transactional(COMMIT)
public class ReflectionComparatorHibernateProxyTest extends UnitilsJUnit4 {
/* The logger instance for this class */
private static Log logger = LogFactory.getLog(ReflectionComparatorHibernateProxyTest.class);
/* A test hibernate entity, with a link to a lazily loaded parent class */
private Child testChild;
protected DataSource dataSource;
@HibernateSessionFactory("org/unitils/reflectionassert/hibernate/hibernate.cfg.xml")
protected SessionFactory sessionFactory;
/* Class under test */
private ReflectionComparator reflectionComparator;
/* True if current test is not for the current dialect */
private boolean disabled;
/**
* Initializes the test fixture.
*/
@Before
public void setUp() throws Exception {
Properties configuration = initDatabaseModule();
this.disabled = !"hsqldb".equals(PropertyUtils.getString(PROPKEY_DATABASE_DIALECT, configuration));
if (disabled) {
return;
}
testChild = new Child(1L, new Parent(1L));
testChild.getParent().setChildren(asList(testChild));
reflectionComparator = createRefectionComparator();
dropTestTables();
createTestTables();
}
/**
* Removes the test database tables from the test database, to avoid inference with other tests
*/
@After
public void tearDown() throws Exception {
if (disabled) {
return;
}
dropTestTables();
}
/**
* Test comparing 2 values with the right one containing a Hibernate proxy.
*/
@Test
public void testGetDifference_rightProxy() {
if (disabled) {
logger.warn("Test is not for current dialect. Skipping test.");
return;
}
Child childWithParentProxy = (Child) sessionFactory.getCurrentSession().get(Child.class, 1L);
Difference result = reflectionComparator.getDifference(testChild, childWithParentProxy);
assertNull(result);
}
/**
* Test comparing 2 values with the left one containing a Hibernate proxy.
*/
@Test
public void testGetDifference_leftProxy() {
if (disabled) {
logger.warn("Test is not for current dialect. Skipping test.");
return;
}
Child childWithParentProxy = (Child) sessionFactory.getCurrentSession().get(Child.class, 1L);
Difference result = reflectionComparator.getDifference(childWithParentProxy, testChild);
ReflectionAssert.assertLenientEquals(childWithParentProxy, testChild);
assertNull(result);
}
/**
* Test comparing 2 values with both containing a Hibernate proxy. The identifiers should have been used
* to compare the proxy values.
*/
@Test
public void testGetDifference_bothProxy() {
if (disabled) {
logger.warn("Test is not for current dialect. Skipping test.");
return;
}
// open 2 session two avoid the values being taken from the cache
Child childWithParentProxy1 = (Child) sessionFactory.openSession().get(Child.class, 1L);
Child childWithParentProxy2 = (Child) sessionFactory.openSession().get(Child.class, 1L);
Difference result = reflectionComparator.getDifference(childWithParentProxy1, childWithParentProxy2);
assertNull(result);
}
/**
* Test comparing 2 values with both containing a different hibnerate proxy. The identifiers should have been used
* to compare the proxy values.
*/
@Test
public void testGetDifference_bothProxyDifferentValue() {
if (disabled) {
logger.warn("Test is not for current dialect. Skipping test.");
return;
}
// open 2 session two avoid the values being taken from the cache
Child childWithParentProxy1 = (Child) sessionFactory.openSession().get(Child.class, 1L);
Child childWithParentProxy2 = (Child) sessionFactory.openSession().get(Child.class, 2L);
Difference result = reflectionComparator.getDifference(childWithParentProxy1, childWithParentProxy2);
assertNotNull(result);
}
/**
* Creates the test tables.
*/
private void createTestTables() {
executeUpdate("create table PARENT (id bigint not null, primary key (id))", dataSource);
executeUpdate("create table CHILD (id bigint not null, parent_id bigint not null, primary key (id))", dataSource);
executeUpdate("alter table CHILD add constraint CHILDTOPARENT foreign key (parent_id) references PARENT", dataSource);
executeUpdate("insert into PARENT (id) values (1)", dataSource);
executeUpdate("insert into PARENT (id) values (2)", dataSource);
executeUpdate("insert into CHILD (id, parent_id) values (1, 1)", dataSource);
executeUpdate("insert into CHILD (id, parent_id) values (2, 2)", dataSource);
}
/**
* Removes the test tables
*/
private void dropTestTables() {
executeUpdateQuietly("drop table CHILD", dataSource);
executeUpdateQuietly("drop table PARENT", dataSource);
}
private Properties initDatabaseModule() {
Properties configuration = (Properties) new ConfigurationLoader().loadConfiguration().clone();
configuration.setProperty("dbMaintainer.autoCreateExecutedScriptsTable", "false");
configuration.setProperty("dbMaintainer.autoCreateDbMaintainScriptsTable", "false");
configuration.setProperty("updateDataBaseSchema.enabled", "false");
configuration.setProperty("database.userName", "sa");
configuration.setProperty("database.password", "");
configuration.setProperty("database.schemaNames", "public");
configuration.setProperty("database.driverClassName", "org.h2.Driver");
configuration.setProperty("database.url", "jdbc:h2:~/test");
configuration.setProperty("database.dialect", "h2");
DatabaseModule databaseModule = Unitils.getInstance().getModulesRepository().getModuleOfType(DatabaseModule.class);
databaseModule.init(configuration);
databaseModule.afterInit();
dataSource = databaseModule.getWrapper("").getTransactionalDataSourceAndActivateTransactionIfNeeded(this);
return configuration;
}
}