SpringMVC+MockMvc+dbUnit+cobertura构建测试框架

本文基于SpringMVC搭建测试框架
通常情况我们可以借助easyMock及powerMock进行单元测试,但有时我们希望进行集成测试,可以通过发送http请求,测试某功能的完整性。
一般情况我们可以通过MockMvc模拟post或get请求,完成测试。但是当碰到delete或update进行测试时,容易对数据库造成污染,这时我们可以借助dbunit,对数据库进行测试数据的准备,测试完成后对事务进行回滚,方便下次测试。
1. maven集成测试组件

    org.springframework
    spring-test
    4.3.10.RELEASE


    junit
    junit
    4.12
    test



    com.github.springtestdbunit
    spring-test-dbunit
    1.1.0
    test


    org.dbunit
    dbunit
    2.4.9
    test


2. 定义测试基类,包括SpringMVC框架的集成,junit集成
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@PropertySource("classpath:common.properties")
@TestPropertySource("classpath:common.properties")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class,
        ServletTestExecutionListener.class,
        DbUnitTestExecutionListener.class}) //@1
@ContextConfiguration(
        {"classpath*:/spring-context.xml", "classpath*:/spring-mvc.xml", "classpath*:/spring-mybatis.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)//@2
@Transactional 
public abstract class BaseSpringJUnitTest {

    public static Logger logger = LoggerFactory.getLogger(BaseSpringJUnitTest.class);

    @Autowired
    private UserInfoService userInfoService;


    private static boolean inited = false;

    /**
     * junit模拟用户名
     */
    private final static String USER_NAME = "admin";

    /**
     * junit模拟验证码
     */
    private final static String VALIDATE_CODE = "1234";

    /**
     * junit模拟密码
     */
    private final static String PASSWORD = "Admin123456";

    public static String token = "";

    protected MockMvc mockMvc; //@3

    @Before //@4
    public void setUp() throws Exception {
        if (!inited) {
            String code = userInfoService.getValidateKey().get("validateKey").toString();
            RedisUtils.set("validCode:" + code, VALIDATE_CODE);
            UserInfoRequestParams params = new UserInfoRequestParams();
            params.setLoginName(USER_NAME);
            params.setPassword(MD5Util.encoderHexByMd5(PASSWORD));
            params.setValidateKey(code);
            params.setValidateCode(VALIDATE_CODE);

            JSONOutputObject result = userInfoService.webLogin(params);
            token = result.get("token").toString();
            TestCase.assertEquals(RsmsConstant.RESULT_SUCCESS_CODE, result.get(RsmsConstant.RESULT_CODE));
            inited = true;
        }
    }

}

@1:ServletTestExecutionListener 用于设置spring web框架启动时的RequestContextHolder本地线程变量。我们的项目比较特殊,在service层中是通过RequestContextHolder获取httpRequest对象(并非通过controller透传),如果不设置,则在service中或者切面中无法获取到request对象

@2:添加事务回滚,避免对数据库的污染

@3:定义MockMvc对象,模拟客户端的http请求

@4:初始化登录信息,根据自身需要设置,有些集成测试场景可能需要登录信息

3.编写测试类
public class UserInfoControllerTest extends BaseSpringJUnitTest {

    @Test
    @DatabaseSetup(type = DatabaseOperation.INSERT, value = {"/data/user-info.xml"})//@1
    public void testDeleteUsers() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        //@2
        String responseString = mockMvc.perform(post("/user/deleteUsers")
                .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
                .content("{\"idList\":10007}")
                .header("Current-Menu-Id", "102100")
                .header("Menu-Id", "102100")
                .accept(MediaType.ALL_VALUE)
                .header("token", token)
                .header("User-Agent", "Windows NT")
        ).andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();
        JSONObject jsonObject = JSONObject.parseObject(responseString);
        Assert.assertEquals(jsonObject.get("resultCode"), "0000");
    }
}

@1:准备测试数据,因为在测试时,如果不自己准备数据,依赖数据库数据,那么数据库数据有可能被其他人误删或者数据库做了迁移或更新之后,我们的测试用例将无法跑通。

@2:通过mockMvc发送http请求,并解析请求结果,判断测试结果的正确性

4.准备测试数据(resource/data/user_info.xml)


    
    

5.jenkins集成,并统计单元测试覆盖率


    org.jacoco
    jacoco-maven-plugin
    0.8.1
    
        
            
                prepare-agent
            
        
        
            report
            prepare-package
            
                report
            
        
    

jenkins添加普通的maven构建任务,设置好git地址

插件管理中安装jacoco插件
build项设置如下
Root POM pom.xml
Goals and options test -Dmaven.repo.local=/opt/repository
构建后操作添加:Record JaCoCo coverage report

统计结果效果如下
单元测试覆盖率统计
6.配置邮件发送

邮件发送本人是集成了cobertura(和jacoco共一样,都是用于覆盖率的统计)

pom集成


          
                org.codehaus.mojo
                cobertura-maven-plugin
                2.7
                
                    
                        html
                        xml
                    
                
            

jenkins全局配置:jenkins->系统管理->系统设置
系统管理员地址:*********@qq.com
Extended E-mail Notification中配置如下
SMTP:smtp.qq.com
后缀@qq.com
点开高级
使用SMTP认证
用户名:*********@qq.com
密码:qq给的授权码(非邮箱的登录密码,授权码的获取:登录QQ邮箱:设置-SMTP设置-开启,需要发送短信,发送短信后,页面会显示授权码)

jenkins构建任务配置邮件发送
构建后操作:增加Editable Email Notification,点开高级,一定要设置triggers,否则无法触发

配置coberture插件.png

邮件发送.png

邮件发送我用的是jelly模板,使用的时候只需要填写模板文件名称(.jelly后缀不需要),模板文件放在jenkins服务器上,具体模板代码见附件一,见下图


邮件模板位置.png

配置trigger.png
7.邮件发送最终效果

邮件主要内容:构建状态、覆盖率整体情况、包覆盖率情况、UT趋势、变更集等等


邮件效果.png
附件一:jelly邮件模板


  
    
      ${project.name}
      
    
    
      
BUILD ${build.result}
构建地址 ${rooturl}${build.url}
项 目: ${project.name}
构建日期: ${it.timestampString}
构建时长: ${build.durationString}
Build cause: ${cause.shortDescription}
Build description: ${build.description}
Built on: ${build.builtOnStr} master

Cobertura报告

趋势

项目覆盖率汇总

Name ${metric.name}
${coberturaResult.name}
${coberturaResult.getCoverage(metric).percentage}%(${coberturaResult.getCoverage(metric)})

Source

${coberturaResult.sourceFileContent}
${coberturaResult.relativeSourcePath}

Source code is unavailable

Coverage Breakdown by ${element.displayName}

Name ${metric.name}
${child.xmlTransform(child.name)}
${childResult.percentage}%(${childResult})
N/A

健康报告

W 描述 分数
${healthReport.description} ${healthReport.score}

变更集

${cs.msgAnnotated}

by ${cs.author}

${spc}${p.editType.name} ${p.path}


Build Artifacts

Build Artifacts

${m.key.displayName}


单元测试

包路径 失败 通过 跳过 总计
${packageResult.getName()} ${packageResult.getFailCount()} ${packageResult.getPassCount()} ${packageResult.getSkipCount()} ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}
${failed_test.getFullName()}

Static Analysis Results

Name Result Total High Normal Low
${action.displayName} ${action.result.numberOfAnnotations} ${action.result.getNumberOfAnnotations('HIGH')} ${action.result.getNumberOfAnnotations('NORMAL')} ${action.result.getNumberOfAnnotations('LOW')}

你可能感兴趣的:(SpringMVC+MockMvc+dbUnit+cobertura构建测试框架)