Thursday, September 20, 2012

In-memory database using Spring 3

In my previous post we discussed about how to run embedded web container. It helped you to remove the dependency of web container for integration testing. In this post, we will discuss about using h2 in-memory database.

What is embedded database and its uses
An embedded database is one you don't see, It's running inside another software product. It stores data entirely in main memory. This kind of database is quite different from the type most people are familiar with, what might be called as exposed database (Oracle, Sql, MySql etc), which are designed for data storage on persistent media. I used in-memory database (h2 db) for integration testing where i wanted application to use  in-memory db so that i can remove the dependency of db while running my integration test cases during maven build. This is also very useful in testing database related code.

Configuration using Spring 3
Spring 3 release has support for in-memory database.Spring 3 supports HSQL, H2 and DERBY natively.In case if you are using spring 3, you can define the data source in spring context file using jdbc:embedded-database tag in the spring-jdbc namespace.
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.0.xsd 
  http://www.springframework.org/schema/jdbc 
  http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
  
  <jdbc:embedded-database id="embedded-datasource" type="H2"> 
    <jdbc:script location="classpath:schema.sql"/> 
    <jdbc:script location="classpath:data.sql"/> 
  </jdbc:embedded-database>

  .............
  ..........
</beans>

This will automatically create a new data source called "embedded-datasource" using H2, and after starting the database, it will load the sql scripts from classpath. In my sql scripts, i had script for creating the schema, table and insert statement for populating the data in db  with which i want to run my test cases.

In case, if you want to use HSQL db or DERBY db, you will have to change type to hsql or derby. That's all you need to do to switch from one db to another, rest all is taken care by spring.
I'm using JPA with hibernate for my application development. There will not be any change in hibernate configuration. You can create entity manager factory as shown below.
<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="embeded-datasource" />
  <property name="persistenceUnitName" value="SamplePU"></property>
</bean>

Sunday, August 26, 2012

Integration Testing using maven jetty plugin

Normally, integration testing for web application involves creating a war and deploying it to web container and starting the container prior to running integration tests.
What happens when application is not deployed and container has not yet started while maven build ? Usually we face this problem while continuous integration build (CI build). I had similar issue in running my integration test cases when Jenkins CI build runs.
The Maven Build Lifecycle includes the "integration-test" phase for running integration tests, which are run separately from the unit tests run during the "test" phase. It runs after "package", so if you run "mvn verify", "mvn install", or "mvn deploy", integration tests will be run along the way. This will cause problem while building application if application is not deployed to container.
Use the Maven Jetty Plugin to start an instance of a server prior to running your integration tests. Jetty provides an HTTP server, HTTP client, and javax.servlet container. Jetty can be started in embedded mode and this is one of its main feature.
If you're using maven project, you can add below maven jetty plugin in project's pom file.
<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <version>6.1.26</version>
  <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <stopKey>stop</stopKey>
    <stopPort>9999</stopPort>
  </configuration>
  <executions>
    <execution>
      <id>start-jetty</id>
      <phase>pre-integration-test</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <scanIntervalSeconds>0</scanIntervalSeconds>
        <daemon>true</daemon>
      </configuration>
    </execution>
    <execution>
      <id>stop-jetty</id>
      <phase>post-integration-test</phase>
      <goals>
        <goal>stop</goal>
      </goals>
    </execution>
  </executions>
</plugin>
How to start/stop jetty
In order to start the jetty in embedded mode before running integration test cases, bind "run" goal with "pre-integration-test" phase and bind "stop" goal with "post-integration-test" phase of maven build life cycle.


Note: You shouldn't run integration test case during test phase. To avoid this, you need to tell surfire/failsafe plugin about pattern of your test cases. This will be discussed in detail in some other post.

Start jetty from command line
mvn jetty:run
It is extremely convenient to leave the plugin running because it can be configured to periodically scan (based on plugin configuration <scanIntervalSeconds>) for changes and automatically redeploy the webapp. This makes development cycle much more faster and eliminates building and deployment of project. Jetty can be started in embedded mode from your regular main() method and it just runs within the context of your application.

Stop jetty from command line
mvn jetty:stop