• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Unit testing: unitils & dbmaintain
 

Unit testing: unitils & dbmaintain

on

  • 8,251 views

 

Statistics

Views

Total Views
8,251
Views on SlideShare
7,435
Embed Views
816

Actions

Likes
6
Downloads
116
Comments
0

8 Embeds 816

http://www.varyonic.com 516
http://www.bejug.org 227
http://blog.oxongeek.org 32
http://www.slideshare.net 24
http://www.bejug.be 8
https://duckduckgo.com 5
http://bejug.org 2
http://translate.googleusercontent.com 2
More...

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Unit testing: unitils & dbmaintain Unit testing: unitils & dbmaintain Presentation Transcript

  • 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
      • What’s committed cannot be changed
      • Sequence is strict
    dbscripts / incremental / 01_initial / 01_users.sql / 02_sprint1 / 01_roles.sql 02_groups.sql
  • Database maintainer – script organization
    • Hierarchic organization
      • Organize per release, sprint
    dbscripts / incremental / 01_initial / 01_users.sql / 02_sprint1 / 01_roles.sql 02_groups.sql
  • Database maintainer – script organization
    • Incremental / repeatable scripts
      • Indexed = incremental
      • Non-indexed = repeatable
      • Update incremental script  error
      • Update repeatable script  re-execute
    dbscripts / incremental / 01_initial / 01_users.sql / 02_sprint1 / 01_roles.sql 02_groups.sql repeatable / view_users_groups.sql
  • Database maintainer – post processing
    • Post-processing scripts
    dbscripts / incremental / 01_initial / 01_users.sql / 02_sprint1 / 01_roles.sql 02_groups.sql repeatable / view_users_groups.sql postprocessing / compile_all.sql create_grants.sql
  • Database maintainer – multi-db
    • Multi database / db user support
      • Define different datasources
        • Usually: same DB – different DB user
      • Indicate target DB in script name
        • Use logical name in script: linked to physical DB at execution time
    01_products.sql 02_ @users _usergroups.sql
  • Database maintainer – multi-db
    • Support for patches
      • Fix on production branch  merge into DEV
     Not allowed: Not in correct sequence dbscripts / incremental / 01_v1.0 / 01_users.sql / 02_#patch_add_status.sql / 02_v1.1 / 01_roles.sql 02_groups.sql
  • Database maintainer – multi-db
    • Support for renames
      • Rename scripts / folders
      • Renumber script / folder indexes
      • Split scripts into folders
      • Move scripts from separate folders together
     Only limitation: relative sequence scripts can't change
  • Database maintainer & the SCM
    • Database setup is put into version control!
    • Atomic: Source and db modifications
      • Comitted together
      • Checked out together
      • Deployed together
     No temporary failures!
  • Database script jar
    • Create jar file with scripts
      • Self contained: Containing own configuration
    • Publish scripts as a deliverable just like war or ear
  • Database maintainer – multi-db
    • Other dbmaintain operations
      • markDatabaseAsUpToDate
      • clearDatabase
      • cleanDatabase
      • disableConstraints
      • updateSequences
  • DbMaintain execution
    • Execution using ant
    • Command line
    <updateDatabase scriptLocations= &quot; ... &quot; > <database url= &quot; ... &quot; ... /> </updateDatabase> > dbmaintain updateDatabase eshop-db.jar – config dbmaintain-st.properties
  • Recreation from scratch
    • From scratch option
      • Possible to modify indexed script  triggers from-scratch recreation
      • No data preservation
      • Perfect for unit / integration test databases
  • Unitils integration
    • Integration with unitils
      • Auto-maintain unit test schema
      • Check for script updates before running tests
      • Make db more ‘test friendly’
        • Disable constraints
        • Update sequences
  • Disable FK & not-null constraints
    • Why disable FK & not null constraints?
      • What we need
      • What we need to write:
    <dataset> <user id=&quot;1&quot; username=&quot;jdoe&quot; /> </dataset> <dataset> <user id=&quot;1&quot; username=&quot;jdoe&quot; firstname=&quot;john&quot; lastname=&quot;Doe&quot; role_id=&quot;1&quot; company_id=&quot;1&quot; /> <role id=&quot;1&quot; rolename=&quot;admin&quot; /> <company id=&quot;1&quot; name=“Agit&quot; /> </dataset>
  • Database maintenance
    • DB maintainer
      • Automatic DB post-processing to make it more test-friendly
        • Disable foreign key & not null constraints
        • Increase value of sequences and identity columns
      • Generate XSD or DTD for dataset definition
  • Mock objects support
    • Brand new mock object library
    • Goals
      • Create the ‘best of breed’
      • Define the simplest possible syntax
      • Promote best practices
  • Mock objects support example public class AlertServiceTest extends UnitilsJUnit4 { Mock <Scheduler> mockScheduler; Mock <Messenger> mockMessenger; // Test data setup @Test public void testSendScheduledAlerts() { mockScheduler.returns (alerts).getScheduledAlerts(myUser)); alertService.sendScheduledAlerts(); mockMessenger.assertInvoked() .sendMessage(alert1); mockMessenger.assertInvoked() .sendMessage(alert2); } }
  • Separate behavior definition from verification
    • Separate behavior definition from verification
    Compared to EasyMock: mockScheduler.returns(alerts).getScheduledAlerts(myUser); alertService.sendScheduledAlerts(); mockMessenger.assertInvoked().sendMessage(alert1); mockMessenger.assertInvoked().sendMessage(alert2); expect(mockScheduler).getScheduledAlerts(myUser) .andReturn(alerts); mockMessenger.sendMessage(alert1); mockMessenger.sendMessage(alert2); replay(); alertService.sendScheduledAlerts();
  • Behavior definition syntax
    • Simple, consistent syntax
      • Behavior definition
      • Invocation asserts
      • No static imports needed
    Compared to EasyMock: mockObject.returns(value).getA(); mockObject.throws(exception).doSomethingInvalid(); mockObject.assertInvoked().doSomething(); expect(mockObject.getA()).andReturn(value); mockObject.doSomethingInvalid(); expectLastCall().andThrow(exception); mockObject.doSomething();
  • Behavior definition syntax
    • Verify invocations: sequence not important
    • Strict sequence
    mockMessenger. assertInvoked() .sendMessage(alert1); mockMessenger. assertInvoked() .sendMessage(alert2); mockMessenger. assertInvokedInSequence() .sendMessage(alert1); mockMessenger. assertInvokedInSequence() .sendMessage(alert2);
  • Behavior definition syntax
    • By default all invocations allowed
      • Default return values: null, empty collection / array
    • Behavior definitions match multiple times
    • To match only once:
    mockScheduler.returns(alerts).getScheduledAlerts(myUser); mockScheduler.getMock().getScheduledAlerts(); -> returns alerts mockScheduler.getMock().getScheduledAlerts(); -> returns alerts mockScheduler.onceReturns(alerts).getScheduledAlerts(myUser); mockScheduler.getMock().getScheduledAlerts(); -> returns alerts mockScheduler.getMock().getScheduledAlerts(); -> returns null
  • Relax argument constraints
    • Mix argument matchers with concrete objects
    • EasyMock: Mixing not possible
    either or mockScheduler.returns(alerts) .getScheduledAlerts( notNull(Date.class), myUser ); expect(mockScheduler).getScheduledAlerts( toDate(“2008/09/18”), myUser ).andReturn(alerts)); expect(mockScheduler).getScheduledAlerts( (Date) notNull(), eq(myUser) ).andReturn(alerts));
  • Relax argument constraints
    • Null means ‘I don’t care’
    • Is same as
    mockScheduler.returns(alerts).getScheduledAlerts( null, null ); mockScheduler.returns(alerts) .getScheduledAlerts( (Date)anyObject(), (User)anyObject() );
  • Relax argument constraints
    • Default argument matching: lenient reflection assert
    • Copy of objects is taken: If object changed during
    • test, object at call time is matched
    mockMessenger.assertInvoked().sendAlert(new Alert(null, null, ChannelType.EMAIL)); mockMessenger.assertInvoked().sendAlert(new Alert(null, null, ChannelType.SMS));
  • Feedback
    • User feedback
      • Observed scenario
      • Suggested assert statements
      • Object contents
    Observed scenario: mockScheduler.getScheduledAlerts ...at mydom.AlertService:55 mockMessenger.send(alert1) ...at mydom.AlertService:76 mockMessenger.send(alert2) ...at mydom.AlertService:76 Suggested assert statements: mockMessenger.assertInvoked().send(alert1); mockMessenger.assertInvoked().send(alert2);
  • Other features
    • Other features
      • Use original implementation for some methods
      • ‘ Dummy’ objects
    PartialMock <Messenger> mockMessenger; @Dummy Message alert1, alert2;
  • Mock injection AlertService alertService; Mock<Scheduler> mockScheduler; Mock<Messenger> mockMessenger; @Before public void setUp() { alertService = new AlertService( mockScheduler. getMock() , mockMessenger. getMock() ); }
    • ‘ Manual’ injection
  • Mock injection @TestedObject AlertService alertService; @InjectIntoByType Mock <Scheduler> mockScheduler ; @InjectIntoByType Mock <Messenger> mockMessenger;
    • Using unitils injection features
  • Injection
    • Injection of any object into any other object
    • Tested object is default target
    • Auto-detect target property
    @InjectInto (target = “targetObject”, property = “targetProperty”) SomeClass injectedObject; TargetClass targetObject; @InjectInto (property = “targetProperty”) SomeClass injectedObject; @TestedObject TargetClass targetObject; @InjectIntoByType SomeClass byTypeInjectedObject; @InjectIntoByName OtherClass byNameInjectedObject; @TestedObject TargetClass targetObject;
  • Unitils architecture
    • Test execution listener
    • Modules listening to test execution
    • Annotations used to instruct modules
    @DataSet, @SpringBean, @Transactional Test Test Listener Database Module DbUnit Module ... Module
  • Unitils architecture
    • Need to extend base class
    org.unitils. UnitilsJUnit3 org.unitils. UnitilsJUnit4 org.unitils. UnitilsTestNG
    • Use custom test runner (JUnit 4 only)
    @RunWith( UnitilsJUnit4TestClassRunner .class)
  • Unitils architecture
    • Modules
      • DatabaseModule
      • DbUnitModule
      • JpaModule
      • HibernateModule
      • SpringModule
      • MockModule
      • EasyMockModule
      • InjectModule
  • Advantages of unitils design
    • Easily extendable and customizable
      • Add new modules or switch implementation
      • Disable modules that you don’t use
        • Automatically if a dependency cannot be found
      • Different target environments
        • Can also be used without spring, hibernate, ...
    • Free choice of unit test framework
      • JUnit 3, JUnit 4, TestNG
  • Spring integration
    • Spring offers similar testing framework
      • Abstraction of test framework
      • Wire test with beans from app-ctx
      • Run tests in transaction
    • Upcoming: integration (2.1)
      • Use spring test with unitils features
  • Spring integration @ContextConfiguration({“eshop-config.xml”, “test-config.xml”}) @DataSet public class UserDaoTest extends AbstractTransactionalUnitilsJUnit4SpringContextTests { @AutoWired 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); } }
  • Roadmap Q3 2009 Q4 2009 DbMaintain 1.1 Unitils 2.3 Unitils 3.0 Separate modules DbMaintain 1.2 Spring test integration Multi db support Various improvements Maven integration Profiles support
  • Links
    • www.unitils.org
      • Project info
      • Cookbook (quick start guide)
      • Tutorial
      • Forum & issue tracker
    Mail me: filip.neven@unitils.org
  • Q&A