springboot+liquibase+h2单元测试方法二

上一篇文章讲述了如何使用springboot远程的@springBootTest注解实现 hibernate的单元测试。好处上一篇文章已经说了(两点:1、使用application-test.yaml搞定一切; 2、两个注解实现一切初始化功能)。但是有好处也有坏处,坏处就是太重量级了,springboot程序小速度还可以,但是一旦springboot程序庞大了,要是你测试一个小小的函数,就不得不喝一杯茶,等 @springbootTest把所有的springboot程序加载一遍。这中间的时间足够你喝两杯茶了

于是这里有另外一种方法来实现大型springboot的entity bean的单元测试:就是自己手动实现上面所有springboot替你实现的步骤,这样你可以非常轻便的完成JPA 的单元测试

项目代码见 github

项目架构,所有基础代码包括liquibase,springboot配置,代码等

springboot+liquibase+hibernate

写hibernate 的JPA配置文件persistence-local.xml

其实这个东西可有可以了现在Is persistence.xml requied when working with Spring and Hibernate?


    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="test-hibernate-local" transaction-type="RESOURCE_LOCAL">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <shared-cache-mode>NONE</shared-cache-mode>
            <properties>
                <property name="hibernate.cache.use_second_level_cache" value="false"/>
            </properties>
        </persistence-unit>
    </persistence>

写spring unit test config 类

类中需要自己指定:

  • liquibase路径
  • 配置LocalContainerEntityManagerFactoryBean, 从而可以直接使用 @PersistenceContext 和 @Transactal两个很有用的注解
  • 自己配置数据源 localDataSource
  • 自己设置 localTransactionManager
  • 自己指定 PersistenceExceptionTranslationPostProcessor

    package com.hibernate.springtest;

    import liquibase.integration.spring.SpringLiquibase;
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.context.annotation.Bean;
    import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;

    import javax.sql.DataSource;

    /**
     * @author wanli zhou
     * @created 2017-10-09 2:11 PM.
     */
    @Configurable
    @EnableTransactionManagement
    public class H2DsConfi {

        @Bean
        public SpringLiquibase springLiquibase(){
            SpringLiquibase ln = new SpringLiquibase();
            ln.setDataSource(localDataSource());
            ln.setChangeLog("classpath:db/changelog/master.xml");
            return ln;
        }

        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
            LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
            bean.setDataSource(localDataSource());
            //https://stackoverflow.com/questions/4736301/is-persistence-xml-requied-when-working-with-spring-and-hibernate
            bean.setPersistenceXmlLocation("classpath*:META-INF/persistence-local.xml");
            bean.setPersistenceUnitName("test-hibernate-local");
            bean.setPackagesToScan("com.hibernate.demo.domain");
            bean.setPersistenceProviderClass(org.hibernate.ejb.HibernatePersistence.class);

            HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
            adapter.setShowSql(true);
            bean.setJpaVendorAdapter(adapter);
            return bean;
        }

        @Bean
        public DataSource localDataSource(){
            DriverManagerDataSource ds = new DriverManagerDataSource();
            ds.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
            ds.setDriverClassName("org.h2.Driver");
            return ds;
        }
        @Bean
        public PlatformTransactionManager localTransactionManager() {
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(entityManagerFactory().getObject());
            txManager.setDataSource(localDataSource());
            return txManager;
        }

        @Bean
        public PersistenceExceptionTranslationPostProcessor exceptionTranslator() {
            return new PersistenceExceptionTranslationPostProcessor();
        }
    }

写单元测试类

这里我们用的是spring 原生的单元测试类,同时显示设置了springcontext的配置类 @ContextConfiguration(classes = H2DsConfi.class)


    package com.hibernate.springtest;

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.hibernate.demo.domain.City;
    import com.hibernate.demo.domain.Province;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.transaction.annotation.Transactional;

    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import java.io.IOException;
    import java.io.StringWriter;
    import java.util.ArrayList;
    import java.util.List;

    /**
     * @author wanli zhou
     * @created 2017-10-09 2:23 PM.
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = H2DsConfi.class)
    public class UseSpringTest {

        @PersistenceContext
        private EntityManager em;
        @Transactional
        @Test
        public void createCSTest(){
            List<City> citis = new ArrayList<>();
            City c = new City();
            c.setCode("c-tc");
            c.setName("test-city");

            citis.add(c);

            Province newP = new Province();
            newP.setName("test-name");
            newP.setCode("p-tc");
            newP.setCities(citis);
            c.setProvince(newP);
            em.persist(newP);
            em.flush();
            List<Province> ps = em.createQuery("select p from Province p where p.name like :name", Province.class)
                    .setParameter("name", "%test%")
                    .getResultList();
            ObjectMapper objectMapper = new ObjectMapper();
            StringWriter stringEmp = new StringWriter();
            try {
                objectMapper.writeValue(stringEmp, ps);
            } catch (IOException e) {
                e.printStackTrace();
            }

            System.out.println("Employee JSON is\n"+stringEmp);
            System.out.println("==");
        }

    }
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
慷慨打赏