3
votes

I am new to Spring and JPA. I developed a project using Spring4 , spring scheduler and JPA and now I want to test my code using Junit test cases. I started with testing my DAO methods. Here is the source code:

This class does the triggering task for the scheduler

public class TriggerTask {


@Autowired
private TriggerDaoBean triggerDaoBean;

public void executeDailyTask() {

    try{
    List<User> users=triggerDaoBean.getClients();
    if (null != users && users.size()>0){

        //do some task
    }

    }catch(Exception e){

    }
}}

The DAO bean is :

@Stateless
public class TriggerDaoBean implements Serializable {

    private static final long serialVersionUID = 1L;


    @PersistenceContext
    private EntityManager em;

    public List<User> getUsers() {      
        List<User> userList = new ArrayList<User>();            
        Query query = em.createQuery(
                "SELECT user FROM USER user");
        userList = (List<User>)query.getResultList();
        if (null != userList && userList.size() > 0) {
            return userList;
        } else {
            return null;
        }
    }

    ....
}

I wrote the below test case:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring-quartz-test.xml" })
@TransactionConfiguration(defaultRollback=true)
@Transactional
public class TriggerTest {

    @Autowired
    TriggerDaoBean triggerDaoBean;

    @Test
    public void getUserListTest() {      
        triggerDaoBean.getUsers();
    }
}

The content of spring-quartz-test.xml is as follows:

<bean id="triggerTask" class="com.test.service.TriggerTask">
    <property name="triggerDaoBean" ref="triggerDaoBean"/>
</bean>

<bean id="triggerDaoBean"
    class="com.test.service.TriggerDaoBean">
</bean>

<bean id="runsrJobDaily" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="triggerTask" />
    <property name="targetMethod" value="executeDailyTask" />
</bean>

And the persistence.xml is as follows:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="forge-default" transaction-type="JTA" >
     <description>Forge Persistence Unit</description>
     <provider>org.hibernate.ejb.HibernatePersistence</provider>
     <jta-data-source>java:/MySqlDS</jta-data-source>


    <class>com.test.persistence.entity.User</class>

    <properties>
     <!--  <property name="hibernate.hbm2ddl.auto" value="create-drop"/> -->
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
      <!--
      <property name="hibernate.ejb.cfgfile" value="modified.hibernate.cfg.xml"/>
      --> 
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hibernate.transaction.flush_before_completion" value="true"/>
    </properties>

  </persistence-unit>
</persistence>

java:/MySqlDS is the JNDI name of datasource. Everytime I run my test, NullPointerException comes for the EntityManager.

Am I doing something wrong?

2

2 Answers

2
votes

I'm my case, you need to append two annotations on your test class.

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootApplicationClass.class)
0
votes

You have to define your entityManager in spring, I do not see the entityManager in the code you posted, you can do it in this way

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

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="example" />
</bean>

<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

Be aware that your are defining your transaction type as JTA in persistence.xml, really do you need global transactions? if not, delete transaction-type="JTA" in persistence.xml

Another thing, for test purposes would be better to use a test database like H2. You can define it in test spring context inside src/test/resources

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence-test.xml"/>
        <property name="persistenceUnitName" value="example-test" />
        <property name="dataSource" ref="dataSourceTest"/>
</bean>

<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="dataSourceTest" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.h2.Driver"/>
        <property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
</bean>

<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server"
        factory-method="createWebServer" init-method="start" lazy-init="true">
        <constructor-arg value="-web,-webAllowOthers,-webPort,11111" />
</bean>

this way you can control the database state, each test will create a database in memory, you can define an import.sql in src/test/resource in order to fill your tables with test data. You have to add de h2 dependency in pom.xml

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.3.174</version>
    <scope>test</scope>
</dependency>