Wednesday, 13 June 2012

How to test Spring MVC with Jetty and custom database - Part II

This is the second part of a series of articles in which I'm writing about how we test our Spring MVC RESTful web services. I'm going to show in a couple of tests how a good test environment can be configured with database and custom database generation.

  • Part I is about the configuration
  • Part II is about the database configuration
  • Part III is about the custom database generation (comming soon)
  • Part IV is about the csv based database generation (comming soon)

Database configuration - Second test

The code can be checked out from https://github.com/bsudy/jettyspring GitHub repository.

In the second test, I'll show how a Spring configuration with JPA can be configured. The configuration similarly to the first test will be used by the normal web.xml in Tomcat as well as by Jetty in the tests. In the second section I'll show how the database can be replaced with a prepared test database.

I created a small test application in the org.moresbycoffee.jettyspring.second package. I has 3 tiers:

  • the lowest is the Data Access Layer consisting of Data Access Objects in the dal package.
  • the middle layer is the "business logic" implemented in the SecondTestService class.
  • and the RESTful WS tier defined in a Spring MVC Controller in the SecondTestRestController class.
The wiring is defined (implemented ?) in the SecondTestConfiguration class. To use the JPA I had to define a entityManagerFactory bean which simple retrieves an EntityManagerFactory from the Peristence. To handle the transactions I had to define a transaction manager, and I had to define a PersistenceAnnotationBeanPostProcessor bean to be able to use the persistence context in the DAL.

    /**
     * @return an entityManager factory to reach the persistence context.
     */
    @Bean
    public EntityManagerFactory entityManagerFactory() {
        return Persistence.createEntityManagerFactory("defaultPU");
    }

    /**
     * @return transaction manager which will manage the transactions using annotations.
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager(entityManagerFactory());
    }

    /**
     * @return necessary bean which will configure the persistence context on all {@link javax.persistence.PersistenceContext} annotation.
     */
    @Bean
    public org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
        return new org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor();
    }

The application beans (DAL and Business Logic) and the REST controller are picked up by Annotation Configuration. I also used annotation to enable transaction management.

In the SecondTestConfiguration I defined the name of the persistence context as defaultPU. The configuration of the Peristence Unit can be found in the persistence.xml and it refers to a h2 database in the jettyspring.h2.db file.

    
      org.hibernate.ejb.HibernatePersistence
      
        
        
        
         
        
         
         
         
         
      
   

We have not taken a look on the service (Business Logic and DAL) yet. Because those are very simple they are implemented only in one-one classes. The FirstEntityDao (implementation of the IFirstEntityDao interface)'s responsibility is to handle the persistence requests regarding to the FirstEntity persistence (database) entity. The database consists only of this entity (table). The Business Logic, implemented in the SecondTestService class is using only this Dao object to provide two services: one to add a new FirstEntity (with it's name) and an other one to list the names of them.

    /**
     * @param name The name of the new entity.
     */
    void addNewEntity(String name);

    /**
     * @return Return all the entity names stored in the system.
     */
    Collection<String> listNames();

Now It was very easy to configure the web.xml and create test which uses the SecondTestRestController. I used the same web.xml as in the Part I and replaced the FirstTestConfiguration with the SecondTestConfiguration.

 
  dispatcherServlet
  org.springframework.web.servlet.DispatcherServlet
  
   contextClass
   org.springframework.web.context.support.AnnotationConfigWebApplicationContext
  
  
   contextConfigLocation
   com.moresby.jettyspring.second.spring.SecondTestConfiguration
  
  1
 

Comment: I forgot to mention one small test. To run the tomcat application you have to copy the database file into the Tomcat directory otherwise it will create a new, empty one.

The tests

To configure the test I also copied the test from Part I and modified the configuration class and the expected value in the listTest test. The test can be found in the JpaServiceTest file. I wouldn't spend more time with this test class, because the replacement of the database is much more interesting. So let's take a look at it.

Replacement of the database

To test the application with the developer/uat/live database is usually not suggested. Therefore in the JpaServiceTestDatabaseTest test suite I replaced the "defaultPU" persistence unit name with "test".

Firstly I extended the SecondTestConfiguration in a nested class of JpaServiceTestDatabaseTest.

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackageClasses = SecondTestRestController.class, basePackages = {"com.moresby.jettyspring.second.beans", "com.moresby.jettyspring.second.dal" })
    @EnableTransactionManagement
    public static class TestConfiguration extends SecondTestConfiguration {

        /** {@inheritDoc} */
        @Override
        public EntityManagerFactory entityManagerFactory() {
            return Persistence.createEntityManagerFactory("test");
        }

    }

Comment:Unfortunately all the annotations have to be applied on this class as well.

Only one step left: I had to define the "test" persistence unit in the persistence.xml to do this, I created a second persistence.xml in the src/test/resource/META-INF directory because it should not be visible from application.

   
      org.hibernate.ejb.HibernatePersistence
      com.moresby.jettyspring.second.domain.FirstEntity
      
        
        
        
         
        
         
         
         
         
      
   

Hurray! In this article we added a database to our application and replaced it with a test database in the tests.

No comments:

Post a Comment