zoukankan      html  css  js  c++  java
  • 如何写单元测试?

    前言

      单元测试的重要性不言而喻。针对测试,有两种用途:一种是针对已完成的功能方法,写单元测试进行验证,这种比较常见。另外一种就是尚未进行功能编码之前,先写测试,测试走通了以后,逻辑思路,功能函数的编码也就很容易了。
    ------------------------------------------------------------------------------------------
      下面呢,将重点介绍spring中针对Controller、Service、Dao层次结构的功能验证测试讲解。Service 与 Dao 层测试基本一致,区别就在于Servie层会执行多次sql,存在事务管理问题。

    Controller  

      可能我们在测试控制层的代码都是启动服务器,在浏览器中输入URL,然后开始测试是否达到预期效果,发生错误的话,修改相关代码并重启服务器再次进行测试。分析一下这个过程,启动服务器-->打开浏览器-->输入URL-->等待返回结果-->修复bug-->重启服务器.....循环。

      MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。

      MockMvc测试过程:
        1、创建请求
        2、设置参数(这一步其实可以设置很多参数,MockMvc提供了丰富的方法,但是本例中只是简单的参数设置,因为方法都较简单,并没有复杂的调用)
        3、mockMvc调用perform,调用controller的业务处理逻辑
        4、perform返回ResultActions,返回操作结果,通过ResultActions,提供了统一的验证方式。

      demo:

     1 @RunWith(SpringJUnit4ClassRunner.class)
     2 @WebAppConfiguration
     3 @ContextConfiguration({"classpath*:/applicationContext.xml", "classpath*:/spring-mvc.xml", "classpath*:/mybatis-config.xml"})
     4 public class BookControllerTest {
     5     @Autowired
     6     private WebApplicationContext wac;
     7     private MockMvc mockMvc;
     8     @Before
     9     public void setup() {
    10         this.mockMvc = webAppContextSetup(this.wac).build();
    11     }
    12     @Test
    13     public void testList() throws Exception {
    14         //创建书籍列表的请求
    15         //请求方式为get
    16         MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders.get("/book/listAll.do");
    17         //此请求并不需要添加请求参数 mockMvc.perform(mockHttpServletRequestBuilder).andExpect(status().isOk())
    18                 .andDo(print());
    19 
    20     }
    21 } 
     1 @RunWith(SpringJUnit4ClassRunner.class)
     2 @WebAppConfiguration
     3 @ContextConfiguration({"classpath*:/applicationContext.xml", "classpath*:/spring-mvc.xml", "classpath*:/mybatis-config.xml"})
     4 @TransactionConfiguration(defaultRollback = false)
     5 @Transactional
     6 public class StoreControllerTest {
     7     @Autowired
     8     private WebApplicationContext wac;
     9 
    10     private MockMvc mockMvc;
    11 
    12     @Before
    13     public void setup() {
    14         this.mockMvc = webAppContextSetup(this.wac).build();
    15     }
    16 
    17     @Test
    18     public void testSave() throws Exception {
    19         //创建书架创建的请求
    20         //请求方式为post
    21         MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders.post("/store/save.do");
    22         //添加编号为MockMvc的书架
    23         mockHttpServletRequestBuilder.param("number", "MockMvc");
    24         //书架为两层
    25         mockHttpServletRequestBuilder.param("level", "2");
    26         mockMvc.perform(mockHttpServletRequestBuilder).andExpect(status().isOk())
    27                 .andDo(print());
    28     }
    29 
    30     @Test
    31     public void testList() throws Exception {
    32         //创建书架创建的请求
    33         //请求方式为post
    34         MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders.post("/store/list.do");
    35         //有些参数我注释掉了,你可以自行添加相关参数,得到不同的测试结果
    36         //status为0的记录
    37         //mockHttpServletRequestBuilder.param("status", "0");
    38         //书架编号为dd的记录
    39         //mockHttpServletRequestBuilder.param("number", "dd");
    40         //第一页
    41         mockHttpServletRequestBuilder.param("page", "1");
    42         //每页10条记录
    43         mockHttpServletRequestBuilder.param("rows", "10");
    44         mockMvc.perform(mockHttpServletRequestBuilder).andExpect(status().isOk())
    45                 .andDo(print());
    46                 
    47     //控制台会打印如下结果:
    48     //MockHttpServletResponse:
    49     //Status = 200 即为后端成功相应
    50     //返回数据
    51     }
    52     
    53 }  
    View Code

    Dao

      使用SpringJunit4集成,进行对Dao层功能方法进行测试。

      指定测试框架:SpringJUnit4ClassRunner.

      装配Spring配置文件,主要获取Dao容器种依赖注入bean.

      demo:

     1 @RunWith(SpringJUnit4ClassRunner.class) //指定测试用例的运行器 这里是指定了Junit4
     2 @ContextConfiguration("classpath:applicationContext.xml")//装配Spring
     3 public class BookDaoTest {
     4     //自动注入,需要将BookDao纳入到Spring容器的管理下,不然会报错
     5     @Autowired
     6     private BookDao bookDao;
     7 
     8     @Test
     9     public void getBookByIdTest() {
    10         Book book1 = bookDao.getBookById("1");
    11         Assert.assertEquals(book1, null);//判断两个参数是否相同,返回true的话则测试通过,不然控制台会亮红灯。
    12         Book book2 = bookDao.getBookById("1002");
    13         Assert.assertEquals(book2.getTitle(), "材料成型概论");
    14         // Assert.assertEquals(book2.getTitle(), "我随便写一个");
    15         //写了三个断言,可以分别进行测试,也可以根据上面三个断言自己编写测试。
    16     }
    17 
    18 }
     1 @RunWith(SpringJUnit4ClassRunner.class) //指定测试用例的运行器 这里是指定了Junit4
     2 @ContextConfiguration("classpath:applicationContext.xml")
     3 
     4 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
     5 //默认回滚,即此类中的方法即使执行成功,数据也并不会真正的修改,方法执行后会回滚。
     6 //因为对数据库的增删改都会回滚,因此便于测试用例的循环利用
     7 //前面书籍模块的测试由于只有查询方法所以没有加这个注解。
     8 //如果想看到数据库中的数据随着测试而发生变化可以去掉这个注解。
     9 public class UserDaoTest {
    10     @Autowired
    11     //自动注入,需要将BookDao纳入到Spring容器的管理下
    12     private UserDao userDao;
    13 
    14     @Test
    15     public void loginTest() {
    16         User user = new User();
    17         user.setUserName("admin");
    18         user.setPassword("123456");
    19         //断言此姓名和密码的用户为空
    20         //密码并没有加密,所以登录失败,返回的用户对象为空。
    21         Assert.assertEquals(userDao.login(user), null);
    22         User user2 = new User();
    23         user2.setUserName("admin");
    24         user2.setPassword(MD5Util.MD5Encode("123456", "UTF-8"));
    25         //断言此姓名和密码的用户可以登录成功,且用户id为2
    26         Assert.assertTrue(userDao.login(user2).getId() == 2);
    27         //执行下面这个断言则会报错。
    28         //Assert.assertTrue(userDao.login(user2).getId() == 3);
    29     }
    30     }

    至此,简单的不同层次的单元测试已经介绍完了。文中使用的测试demo来自于 涵s 的博客,感谢。

    另外,今天浏览搜索单元测试的时候,看到了关于Junit写的很不错的博客(分为初中高级三篇),提供一下链接,方便自己查看:http://blog.csdn.net/andycpp/article/details/1327147/

  • 相关阅读:
    windows下vagrant使用及工作环境配置
    使用docker搭建lnmp环境
    Docker常用命令
    [docker] 管理docker容器中的数据
    python初始化父类错误
    Linux--
    用少于2MB内存存下5百万个介于0到1千万之间的整数
    k路归并:数组、链表
    剑指offer新思路
    阿里电话面试
  • 原文地址:https://www.cnblogs.com/lyc-smile/p/7514303.html
Copyright © 2011-2022 走看看