如何写单元测试?

前言

  单元测试的重要性不言而喻。针对测试,有两种用途:一种是针对已完成的功能方法,写单元测试进行验证,这种比较常见。另外一种就是尚未进行功能编码之前,先写测试,测试走通了以后,逻辑思路,功能函数的编码也就很容易了。
------------------------------------------------------------------------------------------
  下面呢,将重点介绍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/

posted @ 2017-09-13 12:27  蚂蚁分享圈  阅读(905)  评论(0编辑  收藏  举报