当前位置:首页 > 开发 > 系统架构 > 架构 > 正文

Spring4.1新特性——数据库集成测试

发表于: 2014-08-20   作者:jinnianshilongnian   来源:转载   浏览:
摘要: 目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异常处理 Spring4.1新特性——数据库集成测试脚本初始化 Spring4.1新特性——Spring MVC增强 Spring4.1新特性——页面自动化测试框架Spring MVC T

目录

Spring4.1新特性——综述

Spring4.1新特性——Spring核心部分及其他

Spring4.1新特性——Spring缓存框架增强

Spring4.1新特性——异步调用和事件机制的异常处理

Spring4.1新特性——数据库集成测试脚本初始化

Spring4.1新特性——Spring MVC增强

Spring4.1新特性——页面自动化测试框架Spring MVC Test HtmlUnit简介

Spring4.1新特性——静态资源处理增强

 

 

在Spring 4.1之前我们在准备测试数据时可能通过继承AbstractTransactionalJUnit4SpringContextTests,然后调用executeSqlScript()进行测试,其中存在一个主要问题:如果要同时执行多个数据源的初始化就靠不住了,而且使用起来也不是特别便利,Spring4.1提供了@Sql注解来完成这个任务。

 

1、初始化Spring配置: 

    <jdbc:embedded-database id="dataSource1" type="HSQL"/>
    <jdbc:embedded-database id="dataSource2" type="HSQL"/>

    <bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource1"/>
    </bean>

    <bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource2"/>
    </bean>

此处使用jdbc:embedded嵌入数据库来完成测试,数据库使用HSQL。

 

2、 方法级别的@Sql

@RunWith(SpringJUnit4ClassRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ContextConfiguration(value = "classpath:spring-datasource.xml")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class MethodLevelSqlTest {
    private JdbcTemplate jdbcTemplate1;
    private JdbcTemplate jdbcTemplate2;
    @Autowired
    @Qualifier("dataSource1")
    public void setDataSource1(DataSource dataSource1) {
        this.jdbcTemplate1 = new JdbcTemplate(dataSource1);
    }
    @Autowired
    @Qualifier("dataSource2")
    public void setDataSource2(DataSource dataSource2) {
        this.jdbcTemplate2 = new JdbcTemplate(dataSource2);
    }


    @Test
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource1", transactionManager = "txManager1"))
    public void test01_simple() {
        Assert.assertEquals(
                Integer.valueOf(3),
                jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));
    }


    @Test
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource2", transactionManager = "txManager2"))
    public void test02_simple() {
        Assert.assertEquals(
                Integer.valueOf(2),
                jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));
    }

}

方法级别的@Sql在每个方法上都会执行。其中@Sql可以指定多个sql文件,然后通过@SqlConfig指定其编码、分隔符、注释前缀、使用哪个数据源和事务管理器。

 

 

3、类级别的@Sql

@RunWith(SpringJUnit4ClassRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ContextConfiguration(value = "classpath:spring-datasource.xml")
@Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
        config =
        @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                dataSource = "dataSource1", transactionManager = "txManager1"))
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ClassLevelSqlTest {

    private JdbcTemplate jdbcTemplate1;
    @Autowired
    @Qualifier("dataSource1")
    public void setDataSource1(DataSource dataSource1) {
        this.jdbcTemplate1 = new JdbcTemplate(dataSource1);
    }

    @Test
    public void test01_simple() {
        Assert.assertEquals(
                Integer.valueOf(3),
                jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));
    }
}

类级别的对整个测试用例中的每个方法都起作用。 

 

4、指定多个@Sql 

Java8之前需要使用@SqlGroup,而Java8之后直接使用多个@Sql注解即可。

@RunWith(SpringJUnit4ClassRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ContextConfiguration(value = "classpath:spring-datasource.xml")
@Transactional()
@SqlGroup(
        {
                @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
                        config =
                        @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                                dataSource = "dataSource1", transactionManager = "txManager1")),
                @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
                        config =
                        @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                                dataSource = "dataSource2", transactionManager = "txManager2"))
        }
)

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ClassLevelSqlGroupTest {

    private JdbcTemplate jdbcTemplate1;
    private JdbcTemplate jdbcTemplate2;
    @Autowired
    @Qualifier("dataSource1")
    public void setDataSource1(DataSource dataSource1) {
        this.jdbcTemplate1 = new JdbcTemplate(dataSource1);
    }
    @Autowired
    @Qualifier("dataSource2")
    public void setDataSource2(DataSource dataSource2) {
        this.jdbcTemplate2 = new JdbcTemplate(dataSource2);
    }


    @Test
    @Transactional()
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource1", transactionManager = "txManager1"))
    public void test01_simple() {
        Assert.assertEquals(
                Integer.valueOf(3),
                jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));
    }


    @Test
    @Transactional()
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource2", transactionManager = "txManager2"))
    public void test02_simple() {
        Assert.assertEquals(
                Integer.valueOf(2),
                jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));
    }

}

 

也可以通过元注解把注解合并:

@SqlGroup(
        {
                @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
                        config =
                        @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                                dataSource = "dataSource1", transactionManager = "txManager1")),
                @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
                        config =
                        @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                                dataSource = "dataSource2", transactionManager = "txManager2"))
        }
)
@Retention(RUNTIME)
@Target(TYPE)
@interface CompositeSqlGroup {
}

直接使用@CompositeSqlGroup注解即可。

 

5、事务

@RunWith(SpringJUnit4ClassRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@ContextConfiguration(value = "classpath:spring-datasource.xml")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class TransactionalTest {
    private JdbcTemplate jdbcTemplate1;
    private JdbcTemplate jdbcTemplate2;
    @Autowired
    @Qualifier("dataSource1")
    public void setDataSource1(DataSource dataSource1) {
        this.jdbcTemplate1 = new JdbcTemplate(dataSource1);
    }
    @Autowired
    @Qualifier("dataSource2")
    public void setDataSource2(DataSource dataSource2) {
        this.jdbcTemplate2 = new JdbcTemplate(dataSource2);
    }


    @Test
    @Transactional("txManager1")
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource1", transactionManager = "txManager1"))
    public void test01_simple() {
        //判断是在事务中执行
        Assert.assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
        Assert.assertTrue(TestTransaction.isActive());
        Assert.assertEquals(
                Integer.valueOf(3),
                jdbcTemplate1.queryForObject("select count(1) from users", Integer.class));
    }


    @Test
    @Transactional("txManager2")
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource2", transactionManager = "txManager2"))
    public void test02_simple() {
        Assert.assertEquals(
                Integer.valueOf(2),
                jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));
    }


    @Test
    @Transactional("txManager2")
    @Sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},
            config =
            @SqlConfig(encoding = "utf-8", separator = ";", commentPrefix = "--",
                    dataSource = "dataSource2", transactionManager = "txManager2"))
    public void test03_simple() {
        Assert.assertEquals(
                Integer.valueOf(2),
                jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));
        TestTransaction.flagForRollback();
    }

    @Rule
    public TestName testName = new TestName();
    @AfterTransaction
    public void afterTransaction() {
        System.out.println(testName.getMethodName());
        if("test03_simple".equals(testName.getMethodName())) {
            Assert.assertEquals(
                    Integer.valueOf(0),
                    jdbcTemplate2.queryForObject("select count(1) from users", Integer.class));
        }
    }
}

可以使用//判断是在事务中执行TransactionSynchronizationManager.isActualTransactionActive()或TestTransaction.isActive()来判断是否是在事务中执行;通过TestTransaction.flagForRollback();来回滚事务;在测试用例中@AfterTransaction来断言回滚后数据没有插入。

 

相关文章

Spring事务不起作用 问题汇总 

如何测试REQUIRES_NEW事务

 

Spring4新特性

Spring4新特性——泛型限定式依赖注入

Spring4新特性——核心容器的其他改进

Spring4新特性——Web开发的增强

Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 

Spring4新特性——Groovy Bean定义DSL

Spring4新特性——更好的Java泛型操作API 

Spring4新特性——JSR310日期API的支持

Spring4新特性——注解、脚本、任务、MVC等其他特性改进 

          

源码下载

https://github.com/zhangkaitao/spring4-1-showcase/tree/master/spring4.1-dbtest

Spring4.1新特性——数据库集成测试

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
Maven的基本原理和Maven2的新特性 用Maven做项目管理 在Java世界中我们很多的开发人员选择用Ant来构
投递人 itwriter 发布于 2013-02-22 15:53 评论(2) 有560人阅读 原文链接 [收藏] « »   去年 5 月
去年5月份,GitHub官方推出了GitHub for Windows,经过了将近一年的改进,该工具变得更加实用和方便
转发,请保持地址:http://blog.csdn.net/stalendp/article/details/38880997 很长时间没有碰cocos2
Maven的基本原理和Maven2的新特性 用Maven做项目管理 在Java世界中我们很多的开发人员选择用Ant来构
著名科技博客博主Taranfx撰文:Java 1.4到1.5的修改很大,在编译compile-time 方面提升很大,Java 6
著名科技博客博主Taranfx撰文:Java 1.4到1.5的修改很大,在编译compile-time 方面提升很大,Java 6
著名科技博客博主Taranfx撰文:Java 1.4到1.5的修改很大,在编译compile-time 方面提升很大,Java 6
1.1 mysql-cluster简介 简单的说,MySQLCluster实际上是在无共享存储设备的情况下实现的一种完全分
1.1 mysql-cluster简介 简单的说,MySQLCluster实际上是在无共享存储设备的情况下实现的一种完全分
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号