Tuesday, March 17, 2015

Building and Unit Testing (with TDD) Service Layer with below Persistence Layer




Series:







We will:

·        Use TDD to write Unit Test cases and build service layer on top of persistence layer.

o   In last post we have generated persistence layer POJO (Entity and DAOs using Hibernate Tools)

·        Follow the below steps to accomplish the above goal.

1.      Include Spring jar dependencies in Maven.

2.      DBUnit jar dependencies in Maven. (show below with my settings)

3.      Create context.xml with all Spring configuration (shown below with my settings)

4.      Service layer Java class

a.      Create a proper package to hold the service layer POJOS

b.      Create a Java Class

c.      Define/Create an template/empty method

d.      Fill in the body after setting up the Test class and firing Junit to test the implementation

                                                    i.     Implement CRUD

                                                   ii.     I prefer to have my Queries/JQL/Criteria in this layer

                                                  iii.     Include any convenient methods/delegation

e.      Inject necessary classes via annotation

f.       Create necessary DTO (create in a separate package)

5.      Test Classes

a.      Create a proper package to hold the Test Java classes

b.      Create a Java Class

c.      Define a method

d.      Invoke the Service method

e.      Inject necessary classes

f.       Prepare necessary expected data set in xml (DBUnit support DTD and not XSD)

g.      Create necessary xml files to validate actual data (transacted via persistence layer) with that of expected data (prepared via DBUnit framework)

                                                    i.     Prepare necessary DBUnit model (POJO) to create the expected data set if needed in object structure. This is needed by some cases especially while reading the data set.

                                                   ii.     Prepare basic implementation which could be reused for the specific functionality (methods).

h.      Continuous run the method until the implementation of service layer is complete.

i.       After the Service layer is complete re-run necessary and previously written and run Junit test cases to ensure that there is no regression.

6.      Fire the full test suite.

 

Step 1: Include Spring jar dependencies in Maven


Straight forward.

Step 2: Include DBUnit (DBUnit for Spring) jar dependencies in Maven


Straight forward.

Step 3: Create application context for Spring


1.      Include packages (persistence and service layer) for auto scans

<context:component-scan base-package="com.mycos.<package name1>" />

<context:component-scan base-package="com.mycos.<package name2>" />

2.      Setup a DS

   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

             <property name="driverClassName" value="com.mysql.jdbc.Driver" />

3.      Setup up EntityManagerFactory

a.      Use the correct persistenceUnitName used in persistence.xml

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

             <property name="dataSource" ref="dataSource" />

             <property name="persistenceUnitName" value="dpdev"/>

             <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>

4.      Setup JpaVendorAdapter

       <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

             <property name="database" value="MYSQL"/>

             <property name="showSql" value="true"/>

             <property name="generateDdl" value="true"/>

             <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>

5.      Setup TransactionManager

       <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

             <property name="entityManagerFactory" ref="entityManagerFactory" />

       </bean>

6.      Annotate TransactionManager

       <tx:annotation-driven transaction-manager="transactionManager" />

7.      Ensure that necessary namespace and schema locations are included in the context.xml file

a.      Namespace

       xmlns:tx="http://www.springframework.org/schema/tx"

b.      Schemalocation

             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">

Step 4: Service Layer


Follow the approach defined above.

1.      Inject @Service

2.      Inject @Transactional

3.      Inject PersisenceContext

4.      Inject the necessary DAO

5.      Start creating DTO which is map between service VOs with that to Entities generated by HibernateTools

 

@Service

@Transactional

public class XXXService {

    @PersistenceContext

    private EntityManager entityManager;

   

    @Autowired

    private YYYTblHome userTblHome;


    public xxxDTO getXxx(String id) {

       XxxDTO xxxDTO = new XxxDTO();

       XxxTbl xxxTbl = this.xxxTblHome.findById(id);


    public List<XxxDTO> getXxx() {

       Query query = entityManager.createQuery("SELECT p from XxxTbl p");

Step 5: Test classes


1.      Inject Service that you want to test.

2.      Load setup/expected data (DBUnit)

3.      Convert xml into Objects if you want to compare expected vs actual (DBUnit)

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = "classpath*:/context.xml")

@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)

@Transactional

@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,

    DbUnitTestExecutionListener.class })

public class XxxDBUnitTest {

 

    @Autowired

    private XxxxService myService;

   

       protected static final Log log = LogFactory.getLog(XxxDBUnitTest.class);

 

    @Test

@DatabaseSetup(value="/dbunit/xyz.xml",type=DatabaseOperation.REFRESH)

@DatabaseTearDown(value="/dbunit/xyz.xml",type=DatabaseOperation.DELETE)

    public void testXxx() throws Exception {

             ClassPathResource propFileName = new ClassPathResource("/dbunit/xyz.xml);

             log.debug(propFileName.contentLength());

             File myDataFile = propFileName.getFile();

             log.debug(myDataFile.getAbsoluteFile());

             // Load expected data from an XML dataset

        IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(myDataFile);

        ITable expectedTable = expectedDataSet.getTable(table name from the xml”);       

ITable actualTable = new LocationTableHelper(this. myService.getXxx("some data"));

             assertEquals(expectedTable.getRowCount(), actualTable.getRowCount());

 

sample xml file:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE dataset [

<!ELEMENT xxx_tbl EMPTY>

<!ATTLIST xxx_tbl

       xxx_ID CDATA #REQUIRED

       xx_xx CDATA #REQUIRED>    

<!ELEMENT dataset (xxx_tbl+)>

]>

<dataset>

<xxx_tbl xxx _ID="1" xx_xx ="xxx"/>

<xxx_tbl xxx _ID="2" xx_xx ="yyy"/>

<xxx_tbl LOCATION_ID="3" xx_xx ="zzz"/>

</dataset>
 
 

Maven dependencies:
             <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${spring.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-jdbc</artifactId>
                    <version>${spring.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-orm</artifactId>
                    <version>${spring.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-test</artifactId>
                    <version>${spring.version}</version>
             </dependency>
             <dependency>
                    <groupId>org.dbunit</groupId>
                    <artifactId>dbunit</artifactId>
                    <version>${dbunit.version}</version>
             </dependency>
             <dependency>
                    <groupId>com.github.springtestdbunit</groupId>
                    <artifactId>spring-test-dbunit</artifactId>
                    <version>${spring.dbunit.version}</version>
             </dependency>

 

No comments:

Post a Comment