zoukankan      html  css  js  c++  java
  • 使用内存数据库进行单元测试

    转自:https://gerrydevstory.com/2014/04/11/unit-testing-using-mysql-in-memory-database-on-spring/

    Unit Testing Using In-Memory MySQL Database On Spring

    Well the title lied, there’s no such thing as in-memory MySQL database (or at least I won’t be using it for this article). Instead I will use H2 in-memory database setup to run in “MySQL mode”

    1
    2
    3
    4
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="org.h2.Driver"/>
      <property name="url" value="jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
    </bean>

    (thanks to joensson for sharing this technique on SO)

    If your app just uses plain jdbc then adding above datasource to your test context would be sufficient, but if you use JPA/Hibernate the cost of table setup, scanning etc could be quite significant.

    To overcome this you can split the test context using @ContextHierarchy annotation.

    In the example below I have unit tests for two DAOs: AccountDAOTest and CustomerDAOTest:

    1
    2
    3
    4
    5
    6
    7
    @ContextHierarchy({
      @ContextConfiguration("/test-root-context.xml"),
      @ContextConfiguration("AccountDAOTest-context.xml")
    })
    @RunWith(SpringJUnit4ClassRunner.class)
    public class AccountDAOTest {
    }
    1
    2
    3
    4
    5
    6
    7
    @ContextHierarchy({
      @ContextConfiguration("/test-root-context.xml"),
      @ContextConfiguration("CustomerDAOTest-context.xml")
    })
    @RunWith(SpringJUnit4ClassRunner.class)
    public class CustomerDAOTest {
    }

    By doing this Spring test-root-context.xml will be setup once and reused accross all unit tests. Only put components common to all tests in test-root-context.xml. In my case I put the following:

    • DataSource
    • EntityManagerFactory
    • TransactionManager
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- JDBC Data Source -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="org.h2.Driver"/>
      <property name="url" value="jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
    </bean>
     
     
    <!-- EntityManagerFactory -->
    <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
      <property name="persistenceUnitName" value="persistenceUnit" />
      <property name="dataSource" ref="dataSource" />
    </bean>
     
    <!-- Transaction Manager -->
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
      <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    All test specific components go into their respective context.

    Don’t forget to add <tx:annotation-driven/> if your DAO uses it. This can’t be placed on test-root-context.xml because I don’t scan all my DAOs there.

    And lastly — ofcourse — you need to make sure your pom.xml has dependency to spring-test, junit and h2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.3.176</version>
      <scope>test</scope>
    </dependency>
     
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${org.springframework-version}</version>
      <scope>test</scope>
    </dependency>
     
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>

    使用java代码进行bean的配置:

    @Configuration
    @EnableTransactionManagement(proxyTargetClass = true)
    @EnableConfigurationProperties(value = {JpaProperties.class,DataSourceProperties.class})
    public class MfgMasterInMemoryDBConfig {

    // <!-- JDBC Data Source -->
    // <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    // <property name="driverClassName" value="org.h2.Driver"/>
    // <property name="url" value="jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
    // </bean>
    //
    //
    // <!-- EntityManagerFactory -->
    // <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
    // <property name="persistenceUnitName" value="persistenceUnit" />
    // <property name="dataSource" ref="dataSource" />
    // </bean>
    //
    // <!-- Transaction Manager -->
    // <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
    // <property name="entityManagerFactory" ref="entityManagerFactory" />
    // </bean>

    @Autowired
    private JpaProperties jpaProperties;

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
    return new HibernateJpaVendorAdapter();
    }

    @Bean
    public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
    return new EntityManagerFactoryBuilder(jpaVendorAdapter(), jpaProperties.getProperties(), null);
    }

    @Bean
    public EntityManager entityManger(EntityManagerFactory factory) {
    return factory.createEntityManager();
    }

    @Bean
    public DataSource dataSource(DataSourceProperties baseDataSourceProperties){
    DataSource dataSource = DataSourceBuilder
    .create(baseDataSourceProperties.getClassLoader())
    .driverClassName("org.h2.Driver")
    .url("jdbc:h2:mem:testdb;MODE=MySQL")
    .username("sa")
    .password("")
    .build();;
    return dataSource;
    }

    @Bean JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
    JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
    jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
    return jpaTransactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, EntityManagerFactoryBuilder builder) {
    Map<String, Object> hibernateProps = new LinkedHashMap<>();
    hibernateProps.putAll(jpaProperties.getHibernateProperties(dataSource));

    return builder
    .dataSource(dataSource)
    .packages(User.class.getPackage().getName())
    .properties(hibernateProps).jta(false)
    .build();
    }
    }

    Test类的主要注解:


    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes={MfgMasterTestConfiguration.class,MfgMasterInMemoryDBConfig.class})
    //@SpringApplicationConfiguration(classes = MfgMasterDataApplication.class)
    public class MfgMasterDataApplicationTests {

    @Autowired
    public DataSource dataSource;

    @Before
    public void prepareUser(){
    try {
    dataSource.getConnection().createStatement().executeUpdate("INSERT INTO user (id, email, password, created_by, creation_date, enabled, update_date, updated_by, version, firstname, lastname, language) "
    + "VALUES (-1, 'system@mfg.com', 'system', -1, '2015-03-02 17:36:38', 0, NULL, NULL, 0, 'system', 'system', 'US')");
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

    @Test
    public void contextLoads() {
    System.out.println("Done");
    }

    }

  • 相关阅读:
    uboot的配置文件在哪里
    uboot的flash sectore的大小由哪个宏指定
    openwrt中的append-ubi定义在哪里
    vi在行首插入注释符号#
    openwrt设置uboot环境变量在flash上的存储地址
    git重命名分支名
    ifconfig设置ip时出现提示 ifconfig: SIOCSIFFLAGS: Address not available
    jquery checkbox选中、改变状态、change和click事件
    jQuery操作复选框checkbox技巧总结 ---- 设置选中、取消选中、获取被选中的值、判断是否选中等
    checkbox选择根据后台List数据进行回显
  • 原文地址:https://www.cnblogs.com/ly-radiata/p/5212676.html
Copyright © 2011-2022 走看看