前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring集成TestNG测试MVC Controller

Spring集成TestNG测试MVC Controller

作者头像
良辰美景TT
发布2018-12-07 11:34:40
1K0
发布2018-12-07 11:34:40
举报

  在项目中需要写单元测试,如何保证写的单元测试的质量是比较高的。有以下几个原则。

  • 编写具有确定性结果的测试用例。
  • 代码中使用断言,而不是System.out.print语句输出结果,然后人工验证。
  • 对于需要访问数据库的操作或者外部数据,可以使用内存数据库或者EasyMock之类的工具。
  • 测试完数据之后,尽可能的恢复现场(测试之前的环境,这样测试用例便可以重复执行)。

Spring集成TestNG

  • 首先把需要的jar包加入到项目里,因为都是测试相关的,所以scope都是test,引入jar包的pom.xml需要增加如下的依赖(spring 的版本需要在3.2以上):
代码语言:javascript
复制
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
<!-- 用于记录jdbc的日志, 输出的日志格式会带上相应的参数-->
        <dependency>
            <groupId>com.googlecode.log4jdbc</groupId>
            <artifactId>log4jdbc</artifactId>
            <version>1.2</version>
            <scope>test</scope>
        </dependency>
<!-- H2内存数据库, 适合用于处理测试用例的执行-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.197</version>
            <scope>test</scope>
        </dependency>
  • 编写相应的测试用例。代码如下:
代码语言:javascript
复制
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

//@WebAppConfiguration:测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的;value指定web应用的根;
@WebAppConfiguration()
//@ContextHierarchy:指定容器层次
@ContextHierarchy({
                    @ContextConfiguration(locations = {
                                                        "classpath:applicationContext.xml" //这里的applicationContext.xml文件,如果有特殊的bean需要配置,则需要放在src/test/resources目录下
                    }),
                    @ContextConfiguration({
                                            "classpath:spring-mvc.xml"
                    })
})
public class SysUserControllerTest extends AbstractTestNGSpringContextTests {

    //注入web环境的ApplicationContext容器
    @Autowired
    private WebApplicationContext wac;
    
  
    private MockMvc               mockMvc;

    //这里可以执行初使化的数据脚本, 如果没有,也可以不执行这个方法
    SysUserControllerTest() {
        executeSql("sql/mysql/schema.sql");
        executeSql("sql/mysql/import-data.sql");
    }

    //BeforeClass会在testcase执行之前执行
    @BeforeClass
    public void setUp() {
       //MockMvcBuilders.webAppContextSetup(wac).build()创建一个MockMvc进行测试
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    private void executeSql(String sqlPath) {
        DataSource dataSource = new DataSource();
        dataSource.setDriverClassName("net.sf.log4jdbc.DriverSpy"); //采用这个driver 可以方便记录jdbc的日志
        dataSource.setUrl("jdbc:log4jdbc:h2:mem:test;MODE=MySql;DB_CLOSE_DELAY=-1");//H2数据访问的URL
        dataSource.setUsername("sa");
        dataSource.setPassword("");

        Connection connection = null;
        Statement st = null;
        try {
            connection = dataSource.getConnection();
            // Thread.currentThread().getContextClassLoader().getResource(sqlPath) 得到的是以file:/开头的路径, 所以需要截取后6位的字符
            String path = Thread.currentThread().getContextClassLoader().getResource(sqlPath).toString().substring(6);
            st = connection.createStatement();
            st.execute("runscript from '" + path + "'");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (st != null) {
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Test
    public void testadd() throws Exception {
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/sysUser/add.do?username=aaa&name=aaaa&password=aaaaaa&domainUsername=aaaa")). //perform用于执行一个请求
                andDo(MockMvcResultHandlers.print()).  //增加一个结果处理器
                andExpect(MockMvcResultMatchers.status().isOk()). //执行完成后的断言
                andReturn(); //执行完成后返回相应的结果
        String content = result.getResponse().getContentAsString();
        JSONObject jsonObject = JSON.parseObject(content);
        //采用Asser的方式进行断言
        Assert.assertEquals(jsonObject.get("code"), "200");
    }

}

上面的代码需要关注的点有下面几个: 1: 如果spring的配置文件里有bean的构造方式跟线上的不一致,需要在src/main/resources目录下新建spring的配置文件,这样testcase执行的时候加载的是测试环境的文件。比如数据库的datasource bean就有可能不一样。 2:在spring IOC容器之前如果有数据库需要进行初使化的话,则可以在这个测试类的构造方法里执行相应的代码。 3:如果需要在spring IOC容器初使化之后执行相应的数据库初使代码,则可以在testng的@BeforeClass方法里执行。 4:在测试具体的接口的时候,需要用断言对结果进行预测。而不是打印相应的信息。 5:实际项目中可以参考使用H2内存数据库,这样写的sql有什么问题,测试用例也能够尽快发现。 6:这样写的测试类会连同Spring MVC的基础设施(如DispatcherServlet调度、类型转换、数据绑定、拦截器, 最终渲染的视图 @ResponseBody生成的JSON/XML、JSP、Velocity等)但是不会测试web.xml里配置的filter

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.11.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring集成TestNG
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档