Unit testing unitils - dbmaintain Filip Neven
Presentation goal Demonstrate the added value Unitils can give to your projects
Unitils ‘Mission statement’ Provide a good testing environment
Remove boilerplate code
Automate stuff where possible
Help applying best practices
Why Unitils? Tackle complexity of persistence layer testing Many practical problems
A lot of boilerplate code required Offer all kinds of useful functionalities Assertion using reflection
Mock objects
Agenda History
Features by example Persistence layer testing
Reflection assert
Database maintenance
Mock objects Unitils design
Roadmap & summary
Introduction Originates from Ordina Testing & QA task force (2005) Brainstorm
Testing guidelines:  www.unitils.org/guidelines.html
Supporting code    Unitils open source project
Features Persistence layer testing JPA
Hibernate Automatic database maintenance DbMaintain General testing utilities Reflection assert Spring integration
Mock objects
Persistence layer testing Important to test persistence layer Queries are often complex
Two separated parts -> mismatches more likely Testing persistence is difficult Test database
Provide test data Lot of boilerplate code required Depends on technology: Plain old JDBC, ORM, spring
Persistence layer testing guidelines Need control over database & test data Test database
Empty database
Small dataset per group of related tests Typically one dataset per test class
Separate developer schema’s Separate schema per developer Develop in isolation
Test in isolation
Persistence layer testing – DAO example public class UserDao { @PersistenceContext private EntityManager entityManager; public List<User> findByLastName(String lastName) { return entityManager.createQuery( “ select u from User u where u.lastName = :lastName”) .setParameter(“lastName”, lastName) .getResultList(); } // ... }
Persistence layer testing – test example @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest  extends UnitilsJUnit4  { @PersistenceContext   EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Loading test data - example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Loading test data @DataSet Dbunit dataset is loaded before each test Tables are cleared first Default file: same package & name as class UserDaoTest.xml: <?xml version='1.0' encoding='UTF-8'?> <dataset  [… XSD declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; /> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; /> <user id=&quot;3&quot; userName=&quot;janeDoe&quot; /> </dataset>    Put database in known state before each test
Loading test data - possibilities Custom file name Method - specific data set Load multiple datasets @DataSet(&quot;UserData.xml&quot;) public class UserDaoTest extends UnitilsJUnit4 { @DataSet(&quot;UserData-adminUser.xml&quot;) public void testFindAdminUsers() { @DataSet({&quot;ReferenceData.xml&quot;, &quot;UserData.xml&quot;}) public class UserDaoTest extends UnitilsJUnit4 {
Loading test data - XSD XSD for validation & auto completion Automatically generated by Unitils <?xml version='1.0' encoding='UTF-8'?> <dataset   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema- instance&quot; xsi:noNamespaceSchemaLocation=&quot;<path to dataset.xsd file>&quot; > <user id=&quot;1&quot; userName=&quot;johnDoe&quot; age=&quot;54&quot;/> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=&quot;Roe&quot;/> <user id=&quot;3&quot; userName=&quot;janeDoe&quot; firstName=&quot;Jane&quot;/> </dataset>
Loading test data – multi-schema support Multi – schema dataset support <?xml version='1.0' encoding='UTF-8'?> <dataset  xmlns:schema1=&quot;SCHEMA1&quot; xmlns:schema2=&quot;SCHEMA2&quot; > < schema1 :user id=&quot;1&quot; userName=&quot;johnDoe&quot; age=&quot;54&quot;/> < schema2 :user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=&quot;Roe&quot;/> </dataset>
Loading test data – dbunit issues Solve annoying dbunit issue With Unitils: <?xml version='1.0' encoding='UTF-8'?> <dataset  [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; lastName=&quot;Roe&quot;/> <user id=&quot;2&quot; userName=&quot;janeRoe&quot;/> </dataset> With plain dbunit: <?xml version='1.0' encoding='UTF-8'?> <dataset  [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; lastName=&quot;Roe&quot; /> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=“[null]&quot;/> </dataset>   When using dbunit directly, this is not possible:  Once you’ve used a column, you must use it in every record
Verify database contents @ExpectedDataSet Verify database contents after test execution UserDaoTest.testCreateNewUser-expected.xml: <?xml version='1.0' encoding='UTF-8'?> <dataset  [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot;/> </dataset> @ExpectedDataSet public void testCreateNewUser() { // ... }
Transaction support Run each test in a transaction Avoid problems with ‘select for update’ or deferred check constraints
Required in some environments Possible to rollback after each test Facilitates test isolation: DB stays in original state
Enables using pre-filled test DB Default behavior: commit after every test Modify using @Transactional Powered by spring
Transaction support - example @DataSet @Transactional(TransactionMode.ROLLBACK) @JpaEntityManagerFactory(persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
JPA integration - example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext   EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
JPA integration @JpaEntityManagerFactory Create EntityManagerFactory
Connects with unit test database
New EntityManager for each test Attached to unitils transaction Powered by spring
JPA integration – persistence providers Supported persistence providers Hibernate
Toplink
OpenJPA
JPA integration – mapping test Entity / database mapping test Verifies if database structure is in sync with entities
Only works when persistence provider = hibernate @Test public void testMappingToDatabase() { JpaUnitils.assertMappingWithDatabaseConsistent(); } Found mismatches between Java objects and database tables. Applying DDL statements should resolve the problem:  alter table PERSON add column lastName varchar(255);  alter table PRODUCT add column barCode varchar(255);
Reflection assert - example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Reflection assert ReflectionAssert assertReflectionEquals(expectedUser, actualUser); Compares all fields using reflection
Recursively compares inner objects
Loops over collections and arrays
Reports all differences
Reflection assert - leniency Leniency Keep your tests maintainable
Only verify what’s relevant for the test Lenient by default:  Lenient number types
Lenient collection types Leniency options:  assertLenientEquals ( ... ) Lenient order of collections
Ignore java default values (0 or null)
Reflection assert – lenient collection order Ignore order of collections and arrays assertReflectionEquals(expectedCollection, actualCollection, ReflectionComparatorMode.LENIENT_ORDER); assertLenientEquals(expectedCollection, actualCollection); Expected users:  [   john ,  jane   ] Actual users:  [   jane ,  john   ]
Reflection assert – ignore defaults Ignore java default values: 0 or null assertReflectionEquals(expectedCollection, actualCollection, ReflectionComparatorMode.IGNORE_DEFAULTS); assertLenientEquals(expectedUser, actualUser); Expected id:    0 first name:  Jane last name:   null Actual id:    123 first name:   Jane last name:   Doe
Reflection assert – check property value Check property value assertPropertyLenientEquals( &quot; address.houseNr &quot; ,  5 , user); Check property value for all elements in collection assertPropertyLenientEquals( “ userName &quot; ,    Arrays.asList( &quot; johnDoe &quot; , &quot; janeDoe &quot; ), users);
Persistence layer testing - example @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class UserDaoTest  extends UnitilsJUnit4  { @PersistenceContext   EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Base test class with all plumbing @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”,  configFiles={“persistence-test.xml”}) public class BaseDaoTest  extends UnitilsJUnit4  { @PersistenceContext   protected EntityManager entityManager; protected Dao dao = createDao(); @Before public void init() { JpaUnitils.injectEntityManagerInto (dao); } protected abstract DAO createDAO(); }
Test without plumbing public class UserDaoTest extends BaseDaoTest { UserDao userDao = new UserDao(); @Override protected Object getTestedObject() { return userDao; } @Test public void testFindByLastName() { List<User> users = dao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Hibernate support - example @DataSet public class UserDaoTest extends UnitilsJUnit4 { @HibernateSessionFactory(“hibernate-test.cfg.xml”) EntityManagerFactory entityManagerFactory; UserDao userDao; @Before // Instantiate UserDao and inject EntityManagerFactory @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Spring integration – DAO example import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class UserDao extends HibernateDaoSupport { // ... public List<User> findByLastName(String lastName) { return (Long) getHibernateTemplate().findByNamedParam( &quot;from User u where u.lastName = :lastName&quot;,  &quot;user&quot;, user).get(0); } // ... }
Spring integration – test example @SpringApplicationContext({“eshop-config.xml”, “test-config.xml”}) @DataSet public class UserDaoTest extends UnitilsJUnit4 { @SpringBean(“userDao”) UserDao userDao; @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;,  Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
Spring integration - configuration eshop-config.xml <bean id=&quot;userDao&quot; class=&quot;eshop.dao.UserDao&quot;> <property name=&quot;sessionFactory&quot; ref=&quot;sessionFactory&quot;/> </bean> <bean id=&quot;sessionFactory&quot; class=&quot;..AnnotationSessionFactoryBean&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;/>  <property name=&quot;annotatedClasses&quot;> <list> <value>eshop.model.User</value> </list> </property> </bean> <bean id=&quot;dataSource&quot;> … </bean> test-config.xml <bean id=&quot;dataSource&quot;  class=&quot;org.unitils..UnitilsDataSourceFactoryBean&quot;/>
Spring integration @SpringApplicationContext Application context is loaded
Typically application & test specific config file @SpringBean Inject bean from ApplicationContext into test
Other possibilities @SpringBeanByName, @SpringBeanByType
Automatic database maintenance Automatic database maintenance Currently still part of unitils (2.2)
Split off into DbMaintain project 1.0 released in february Will be removed from Unitils
Why automatic database maintenance? Drawbacks of manual maintenance Lot of databases – lot to maintain
What was rolled out where?    Time consuming, error prone
Why automatic database maintenance? Fully automatic deployments Enables frequent deployments
Tester / customer can trigger deployment Shorter feedback cycle Enables automatic integration tests
Database maintainer – basic usage Folder with indexed scripts Database table stores executed scripts info Rollout: Only apply new scripts FILE_NAME VERSION LAST_MODIFIED CHECKSUM EXECUTED_AT SUCCEEDED 01_users.sql 1 1206695947921 15a4be468g 2008-09-17 20:23:12 1 02_roles.sql 1 1206695947996 79a5b32g10 2008-09-18 10:15:12 1 DBMAINTAIN_SCRIPTS dbscripts / 01_users.sql / 02_roles.sql
Database maintainer – script organization Work incremental Database change = new script

Unit testing: unitils & dbmaintain

  • 1.
    Unit testing unitils- dbmaintain Filip Neven
  • 2.
    Presentation goal Demonstratethe added value Unitils can give to your projects
  • 3.
    Unitils ‘Mission statement’Provide a good testing environment
  • 4.
  • 5.
  • 6.
  • 7.
    Why Unitils? Tacklecomplexity of persistence layer testing Many practical problems
  • 8.
    A lot ofboilerplate code required Offer all kinds of useful functionalities Assertion using reflection
  • 9.
  • 10.
  • 11.
    Features by examplePersistence layer testing
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
    Introduction Originates fromOrdina Testing & QA task force (2005) Brainstorm
  • 17.
    Testing guidelines: www.unitils.org/guidelines.html
  • 18.
    Supporting code  Unitils open source project
  • 19.
  • 20.
    Hibernate Automatic databasemaintenance DbMaintain General testing utilities Reflection assert Spring integration
  • 21.
  • 22.
    Persistence layer testingImportant to test persistence layer Queries are often complex
  • 23.
    Two separated parts-> mismatches more likely Testing persistence is difficult Test database
  • 24.
    Provide test dataLot of boilerplate code required Depends on technology: Plain old JDBC, ORM, spring
  • 25.
    Persistence layer testingguidelines Need control over database & test data Test database
  • 26.
  • 27.
    Small dataset pergroup of related tests Typically one dataset per test class
  • 28.
    Separate developer schema’sSeparate schema per developer Develop in isolation
  • 29.
  • 30.
    Persistence layer testing– DAO example public class UserDao { @PersistenceContext private EntityManager entityManager; public List<User> findByLastName(String lastName) { return entityManager.createQuery( “ select u from User u where u.lastName = :lastName”) .setParameter(“lastName”, lastName) .getResultList(); } // ... }
  • 31.
    Persistence layer testing– test example @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 32.
    Loading test data- example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 33.
    Loading test data@DataSet Dbunit dataset is loaded before each test Tables are cleared first Default file: same package & name as class UserDaoTest.xml: <?xml version='1.0' encoding='UTF-8'?> <dataset [… XSD declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; /> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; /> <user id=&quot;3&quot; userName=&quot;janeDoe&quot; /> </dataset>  Put database in known state before each test
  • 34.
    Loading test data- possibilities Custom file name Method - specific data set Load multiple datasets @DataSet(&quot;UserData.xml&quot;) public class UserDaoTest extends UnitilsJUnit4 { @DataSet(&quot;UserData-adminUser.xml&quot;) public void testFindAdminUsers() { @DataSet({&quot;ReferenceData.xml&quot;, &quot;UserData.xml&quot;}) public class UserDaoTest extends UnitilsJUnit4 {
  • 35.
    Loading test data- XSD XSD for validation & auto completion Automatically generated by Unitils <?xml version='1.0' encoding='UTF-8'?> <dataset xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema- instance&quot; xsi:noNamespaceSchemaLocation=&quot;<path to dataset.xsd file>&quot; > <user id=&quot;1&quot; userName=&quot;johnDoe&quot; age=&quot;54&quot;/> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=&quot;Roe&quot;/> <user id=&quot;3&quot; userName=&quot;janeDoe&quot; firstName=&quot;Jane&quot;/> </dataset>
  • 36.
    Loading test data– multi-schema support Multi – schema dataset support <?xml version='1.0' encoding='UTF-8'?> <dataset xmlns:schema1=&quot;SCHEMA1&quot; xmlns:schema2=&quot;SCHEMA2&quot; > < schema1 :user id=&quot;1&quot; userName=&quot;johnDoe&quot; age=&quot;54&quot;/> < schema2 :user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=&quot;Roe&quot;/> </dataset>
  • 37.
    Loading test data– dbunit issues Solve annoying dbunit issue With Unitils: <?xml version='1.0' encoding='UTF-8'?> <dataset [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; lastName=&quot;Roe&quot;/> <user id=&quot;2&quot; userName=&quot;janeRoe&quot;/> </dataset> With plain dbunit: <?xml version='1.0' encoding='UTF-8'?> <dataset [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot; lastName=&quot;Roe&quot; /> <user id=&quot;2&quot; userName=&quot;janeRoe&quot; lastName=“[null]&quot;/> </dataset> When using dbunit directly, this is not possible: Once you’ve used a column, you must use it in every record
  • 38.
    Verify database contents@ExpectedDataSet Verify database contents after test execution UserDaoTest.testCreateNewUser-expected.xml: <?xml version='1.0' encoding='UTF-8'?> <dataset [… namespace declaration …]> <user id=&quot;1&quot; userName=&quot;johnDoe&quot;/> </dataset> @ExpectedDataSet public void testCreateNewUser() { // ... }
  • 39.
    Transaction support Runeach test in a transaction Avoid problems with ‘select for update’ or deferred check constraints
  • 40.
    Required in someenvironments Possible to rollback after each test Facilitates test isolation: DB stays in original state
  • 41.
    Enables using pre-filledtest DB Default behavior: commit after every test Modify using @Transactional Powered by spring
  • 42.
    Transaction support -example @DataSet @Transactional(TransactionMode.ROLLBACK) @JpaEntityManagerFactory(persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 43.
    JPA integration -example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 44.
    JPA integration @JpaEntityManagerFactoryCreate EntityManagerFactory
  • 45.
    Connects with unittest database
  • 46.
    New EntityManager foreach test Attached to unitils transaction Powered by spring
  • 47.
    JPA integration –persistence providers Supported persistence providers Hibernate
  • 48.
  • 49.
  • 50.
    JPA integration –mapping test Entity / database mapping test Verifies if database structure is in sync with entities
  • 51.
    Only works whenpersistence provider = hibernate @Test public void testMappingToDatabase() { JpaUnitils.assertMappingWithDatabaseConsistent(); } Found mismatches between Java objects and database tables. Applying DDL statements should resolve the problem: alter table PERSON add column lastName varchar(255); alter table PRODUCT add column barCode varchar(255);
  • 52.
    Reflection assert -example @DataSet @JpaEntityManagerFactory(persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto(userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 53.
    Reflection assert ReflectionAssertassertReflectionEquals(expectedUser, actualUser); Compares all fields using reflection
  • 54.
  • 55.
  • 56.
  • 57.
    Reflection assert -leniency Leniency Keep your tests maintainable
  • 58.
    Only verify what’srelevant for the test Lenient by default: Lenient number types
  • 59.
    Lenient collection typesLeniency options: assertLenientEquals ( ... ) Lenient order of collections
  • 60.
    Ignore java defaultvalues (0 or null)
  • 61.
    Reflection assert –lenient collection order Ignore order of collections and arrays assertReflectionEquals(expectedCollection, actualCollection, ReflectionComparatorMode.LENIENT_ORDER); assertLenientEquals(expectedCollection, actualCollection); Expected users: [ john , jane ] Actual users: [ jane , john ]
  • 62.
    Reflection assert –ignore defaults Ignore java default values: 0 or null assertReflectionEquals(expectedCollection, actualCollection, ReflectionComparatorMode.IGNORE_DEFAULTS); assertLenientEquals(expectedUser, actualUser); Expected id: 0 first name: Jane last name: null Actual id: 123 first name: Jane last name: Doe
  • 63.
    Reflection assert –check property value Check property value assertPropertyLenientEquals( &quot; address.houseNr &quot; , 5 , user); Check property value for all elements in collection assertPropertyLenientEquals( “ userName &quot; , Arrays.asList( &quot; johnDoe &quot; , &quot; janeDoe &quot; ), users);
  • 64.
    Persistence layer testing- example @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class UserDaoTest extends UnitilsJUnit4 { @PersistenceContext EntityManager entityManager; UserDao userDao; @Before public void init() { JpaUnitils.injectEntityManagerInto (userDao); } @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals (&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 65.
    Base test classwith all plumbing @DataSet @JpaEntityManagerFactory (persistenceUnit=“eshop”, configFiles={“persistence-test.xml”}) public class BaseDaoTest extends UnitilsJUnit4 { @PersistenceContext protected EntityManager entityManager; protected Dao dao = createDao(); @Before public void init() { JpaUnitils.injectEntityManagerInto (dao); } protected abstract DAO createDAO(); }
  • 66.
    Test without plumbingpublic class UserDaoTest extends BaseDaoTest { UserDao userDao = new UserDao(); @Override protected Object getTestedObject() { return userDao; } @Test public void testFindByLastName() { List<User> users = dao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 67.
    Hibernate support -example @DataSet public class UserDaoTest extends UnitilsJUnit4 { @HibernateSessionFactory(“hibernate-test.cfg.xml”) EntityManagerFactory entityManagerFactory; UserDao userDao; @Before // Instantiate UserDao and inject EntityManagerFactory @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 68.
    Spring integration –DAO example import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class UserDao extends HibernateDaoSupport { // ... public List<User> findByLastName(String lastName) { return (Long) getHibernateTemplate().findByNamedParam( &quot;from User u where u.lastName = :lastName&quot;, &quot;user&quot;, user).get(0); } // ... }
  • 69.
    Spring integration –test example @SpringApplicationContext({“eshop-config.xml”, “test-config.xml”}) @DataSet public class UserDaoTest extends UnitilsJUnit4 { @SpringBean(“userDao”) UserDao userDao; @Test public void testFindByLastName() { List<User> users = userDao.findByLastName(&quot;Doe&quot;); assertPropertyLenientEquals(&quot;userName&quot;, Arrays.asList(&quot;johnDoe&quot;, &quot;janeDoe&quot;), users); } }
  • 70.
    Spring integration -configuration eshop-config.xml <bean id=&quot;userDao&quot; class=&quot;eshop.dao.UserDao&quot;> <property name=&quot;sessionFactory&quot; ref=&quot;sessionFactory&quot;/> </bean> <bean id=&quot;sessionFactory&quot; class=&quot;..AnnotationSessionFactoryBean&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;/> <property name=&quot;annotatedClasses&quot;> <list> <value>eshop.model.User</value> </list> </property> </bean> <bean id=&quot;dataSource&quot;> … </bean> test-config.xml <bean id=&quot;dataSource&quot; class=&quot;org.unitils..UnitilsDataSourceFactoryBean&quot;/>
  • 71.
    Spring integration @SpringApplicationContextApplication context is loaded
  • 72.
    Typically application &test specific config file @SpringBean Inject bean from ApplicationContext into test
  • 73.
  • 74.
    Automatic database maintenanceAutomatic database maintenance Currently still part of unitils (2.2)
  • 75.
    Split off intoDbMaintain project 1.0 released in february Will be removed from Unitils
  • 76.
    Why automatic databasemaintenance? Drawbacks of manual maintenance Lot of databases – lot to maintain
  • 77.
    What was rolledout where?  Time consuming, error prone
  • 78.
    Why automatic databasemaintenance? Fully automatic deployments Enables frequent deployments
  • 79.
    Tester / customercan trigger deployment Shorter feedback cycle Enables automatic integration tests
  • 80.
    Database maintainer –basic usage Folder with indexed scripts Database table stores executed scripts info Rollout: Only apply new scripts FILE_NAME VERSION LAST_MODIFIED CHECKSUM EXECUTED_AT SUCCEEDED 01_users.sql 1 1206695947921 15a4be468g 2008-09-17 20:23:12 1 02_roles.sql 1 1206695947996 79a5b32g10 2008-09-18 10:15:12 1 DBMAINTAIN_SCRIPTS dbscripts / 01_users.sql / 02_roles.sql
  • 81.
    Database maintainer –script organization Work incremental Database change = new script