2. Agenda
In Memory Unit Testing - Need
In Memory Unit Testing - Architecture
In Memory Unit Testing – Tools Needed
In Memory Unit Testing – Steps
In Memory Unit Testing – Code Samples
In Memory Unit Testing – Challenges
Thanks
3. In Memory Unit Testing - Need
• Unit Tests might be required to run at following stages – during code development,
code integration, build creation and might be at deployment time too.
• During Development – Tests have to be very fast – should take less than 5 seconds
due to frequent runs of tests and that frequent code changes didn’t break anything else
• As far as unit testing is concerned, setting up connection with actual DB and running
actual queries etc. is very slow
• In-Memory testing is better than no testing at all – since we generally mock db
connection objects etc. and don’t write unit tests for DAO Layer at all while generally
there is too much code and logic at DAO layer too
• During deployments – unit tests are run before starting of the application or other
system components so DB might not be available or we don’t expect DB to be
available for unit test runs
4. In Memory Unit Testing – Need…Contd..
• If unit tests fail due to DB not being available – it would still be counted as a failure and
deployment might not proceed
• Tests can be run on systems that don’t have connectivity to real databases which is
generally the case for build boxes
• Tests are run on consistent data because data resides in checked in xml files. With
actual DB, we will have to prepare data on all developer systems.
• Parallel Test Execution – Each test can have its own In – memory database so tests
can be run in parallel as far as data is concerned. DB locking and other contentious
issues will not occur
• With Maven, it has become easy to run unit tests and there are projects where
successful run of unit tests during deployments is a Go – No GO factor for production
deployments – if unit tests fail, deployment is a No GO
5. In Memory Unit Testing – Need…Contd..
• Using actual DB for unit tests might corrupt the test data because that is usually meant
for integration tests
• Code Coverage – If organization mandates a certain percentage of code coverage for
unit tests, DAO code can’t be left without unit tests as it might not be possible to
achieve desired coverage leaving DAO layer code. Mocking Connection etc. results in
very fake kind of unit tests with no value and there is no use of achieving code
coverage just for the sake of formality
7. In-Memory Unit Testing – Tools Needed
First, you need a database which supports In – Memory mode i.e. full db gets loaded in
memory, tables & data are created in memory and all these run time structures vanish once
tests finish. Nothing persists on disk. H2 , HSQL and MySQL databases support in-memory
mode. I used HSQLDB for my project and this presentation
Secondly, You need an API to Connect to In-Memory database, table creation , preparing and
loading of data. I used Apache DBUnit for this - dbunit-2.4.9.jar
Then you need a Unit Testing Framework like JUnit etc.
So you will write unit tests in JUnit, connecting to in – memory database ( which is equivalent
to your real RDBMS ) for your data needs
8. In-Memory Unit Testing – Steps
Include HSQL DB Jar to your project in any way suitable to you
Use below values for connection string,
private static final String JDBC_DRIVER = org.hsqldb.jdbcDriver.class.getName();
private static final String JDBC_URL ="jdbc:hsqldb:mem:tests";
private static final String USER = "sa";
private static final String PASSWORD = "";
User and Password are fixed and notice URL’s :mem: portion which indicates in –
memory mode.
Include Apache DbUnit and JUnit dependencies to your project
9. In-Memory Unit Testing – Code Samples…Java
As illustrated in code sample, we create DB connection & db tables at @BeforeClass time and set up data at @Before time.
Public class TestClass{
private static final String JDBC_DRIVER = org.hsqldb.jdbcDriver.class.getName();
private static final String JDBC_URL ="jdbc:hsqldb:mem:tests";
private static final String USER = "sa";
private static final String PASSWORD = "";
private static IDatabaseTester databaseTester;
private IDataSet dataSet1,dataSet2;
@BeforeClass
public static void inMemDBSetUp() throws Exception{
databaseTester=new JdbcDatabaseTester(JDBC_DRIVER,JDBC_URL,USER,PASSWORD);
Connection connection=databaseTester.getConnection().getConnection();
createTables(connection);
}
@AfterClass
public static void inMemDbCleanUp(){}
…….contd…
10. In-Memory Unit Testing – Code Samples…Java..Contd
@Before
public void testDataSetUp() throws Exception{
service=new Service() ; //assume this is your service class to be tested
service.setDBConnection(databaseTester.getConnection().getConnection());
dataSet1=readDataSet1();
cleanlyInsert(dataSet1);
dataSet2=readDataSet2(); etc
cleanlyInsert(dataSet2);
}
11. In-Memory Unit Testing – Code Samples…Java..Contd
private static void createTables(Connection connection){
//Here we use connection object to create tables, table constraints etc like in real DB
//This will be very similar to plain jdbc code where your prepare statements from SQLS and execute those statements
}
//This method will read data table data kept in XML file and will pass on to cleanlyInsert method
private IDataSet readDataSet1() throws Exception {
return new FlatXmlDataSetBuilder().build(TestClass.class.getResourceAsStream("/data.xml"));
}
//similarly readDataSet2() method etc
//this method will load data into tables
private void cleanlyInsert(IDataSet dataSet) throws Exception {
databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
databaseTester.setDataSet(dataSet);
databaseTester.onSetup();
}
}//end testclass
12. In-Memory Unit Testing – Code Samples…XML data
Data read in Java class resides in XML files in below format, data.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<TABLE_NAME COLUMN_1=VALUE1, COLUMN2=VALUE2 …/>
</dataset>
Each row in above xml represents a single row in mentioned table at start of tag.
Similarly, a second row can be added for another table and so on…
13. In-Memory Unit Testing – Challenges
First challenge that I faced is the syntax differences between actual database system
and HSQLDB so there might be quite a bit of effort required for creation of DDL
queries like CREATE TABLE statement etc.
Schema Definition: I found it very hard to include schema name in data xml. I didn’t
found a way out for that.