博客
关于我
开发中的单元测试
阅读量:112 次
发布时间:2019-02-27

本文共 4076 字,大约阅读时间需要 13 分钟。

由于对Dao层的测试时间成本相对来说比较大,而Dao层本来就没有复杂的逻辑所以在这选了Service和Controller层的单元测试.

基于Spring的单元测试库Spring-Test

这对于在用Spring的亲们应该不陌生, SpringTest可以在单元测试中初始化Spring的上下文, 这一点就已经相当方便了.

通过

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = "classpath*:applicationContext.xml")

这两个注解就可以实现, Spring的配置文件应该放在classpath中. Maven的就放在test文件夹中的resources文件夹中.

注意:

我曾经遇到过有朋友会将HttpSesson或者ServletContext注入到Service中.

@AutowiredHttpSession session;@AutowiredServletContext context;

这样用起来虽然简单, 但是会给单元测试造成困难. 原因: session和servletContext都是在服务器启动时创建, 而单元测试并没有去启动服务器所以Spring是没有办法去注入这两个东西的. 而且(个人经验)这种写法并不符合常规,我们可以通过Controller层去获取然后传入到Service层中, 我暂时还没有找到在单元测试注入到Spring容器的方法. (由于上面用的注解注入, 用setter并不能解决问题, 去掉注解则会造成代码污染.) 如果一定要用到的~只要不使用注解的方法去注入,然后加上setter都可以让spring成功初始化,在测试用到时通过setter注入就可以.

Service层.

在工作的时候,我也只是用SpringTest初始化容器,然后调用一下Service的方法这样去测试,但是这样的测试当遇到错误时,我们还需要去考虑到底是Service的错还是Dao层的问题.而且Spring去初始化用时非常长,花这么多时间去做一个单元测试并不是太合理. 这里我们可以使用EasyMock去构造一个Dao层方法的Mock对象, 录制所需要的执行的方法并在Service层中回放.下面我大概说说用法.

private BaseDAO
adminBaseDao;//需要通过setter方法注入到Service中//在测试方法中EasyMock.createMock(BaseDAO.class);EasyMock.expect(adminBaseDao.get("from Admin a where a.phone=? and a.password=?", new Object[]{ "110","123"})).andReturn(result);EasyMock.replay(adminBaseDao);

测试Service层的时候其实已经没有必要去初始化Spring了,

至于注入到Service 方法1:可以直接new一个~然后通过setter将用到的mock出来的Dao注入进去.

方法2:使用Unitils中的Inject模块使用@InjectInto注解就可以不用添加setter方法

@TestedObjectprivate AdminService adminService;@Mock@InjectInto(target = "adminService", property = "adminBaseDao")private BaseDAO
adminBaseDao;

这样去测试Service层的好处是, Dao层的方法都是自己模拟出来的, 如果Service操作指定的数据是正常的那么当出现问题的时候就知道应该是Dao层的问题. 而且跳过了Spring初始化, 那个速度真的快了超多.

对于Controller层

使用Struts2的小伙伴可以使用Struts2的 Struts2Test的模块

public class AdminActionTest extends StrutsSpringJUnit4TestCase

注意:@Before的方法名不能用setUp. 根据JUnit3 初始化方法会使用setUp作为方法名,但是在这里Struts2Test在源码里面已经有这个setUp方法, 你在写一个会覆盖他的方法, 导致request和response无法mock出来.

贴段Struts2Test源代码:

@Beforepublic void setUp() throws Exception {       super.setUp();    this.initServletMockObjects();    this.setupBeforeInitDispatcher();    this.initDispatcherParams();    this.initDispatcher(this.dispatcherInitParams);}

在测试时按上面EasyMock的方法将Service Mock出来, 然后再通过setter或者Unitils inject 注入到Action里面, 然后需要用ActionProxy来注入…(在里面有一个executeAction的方法可以直接执行Action,如果是通过初始化Spring来测试的就可以使用,但是这样没办法注入MockService), 因为ActionProxy并不是通过request来获取参数的, 所以参数用到的对象也应该用setter或者inject 注入到Action中.

ActionProxy proxy = getActionProxy("/admin/login.action");AdminAction action = ((AdminAction) proxy.getAction()).setAdminService(adminService);action.setAdmin(admin);action.setSession(request.getSession());String result = proxy.execute();Assert.assertEquals("success", result);

如果是使用SpringMVC的朋友其实道理都是一样的.都是Mock这个注入进去, Mock那个注入进去, SpringMVC的,mock request和mock response需要自己去创建, 直接上代码了;

private MockHttpServletRequest request = new MockHttpServletRequest();private MockHttpServletResponse response = new MockHttpServletResponse();@Beforepublic void setup() {       awardControler = new AwardControler();    awardService = EasyMock.createMock(AwardService.class);    awardControler.setAwardService(awardService);}@Testpublic void testGetAwardDetail() throws Exception {       //create mock return object    Award award = new Award();    award.setId("1");    award.setName("测试1");    award.setStatus("未发放");    request.setRequestURI("/awardController/getAwardDetail.do");    request.setMethod(HttpMethod.POST.name());    request.setParameter("id", "1");    EasyMock.expect(awardService.getAwardById("1")).andReturn(award);    EasyMock.expect(awardService.getAwardStatusJSON()).andReturn("ok");    EasyMock.replay(awardService);    ModelAndView modelAndView = awardControler.getAwardDetail(request, response);    //create expect model    Map
expected = new HashMap
(); expected.put("id", "1"); expected.put("Id", "1"); expected.put("status", "ok"); ModelAndViewAssert.assertViewName(modelAndView, "souche/award/detail.jsp"); ModelAndViewAssert.assertModelAttributeValues(modelAndView, expected);}

最后

软件测试交流群,加群qq(**644956177)**群里有技术交流和资源分享。

转载地址:http://kghf.baihongyu.com/

你可能感兴趣的文章
流媒体音视频服务云管理平台EasyNVS平台中视频播放页面出现错误码的问题解决
查看>>
AI视频结构化智能安防平台EasyCVR自定义场景下的网页标题优化
查看>>
渗透测试工具实战技巧合集
查看>>
渗透测试学习笔记之案例五
查看>>
Pentest Wiki Part4 后渗透(二)
查看>>
微信getUserInfo接口
查看>>
Shell脚本实现Linux回收站
查看>>
R中rm()函数
查看>>
tomcat配置虚拟目录后出现404的解决方法
查看>>
leetcode之使数组中所有元素相等的最小操作数(C++)
查看>>
Sidecar原理分析
查看>>
【Python】Dvwa文件上传python脚本(已实现)
查看>>
VS2012创建项目弹出 “未找到与约束”错误提示(已解决)
查看>>
asp,asp.net中关于双引号和单引号的用法!
查看>>
Cannot determine value type from string varchar问题
查看>>
Redis Desktop Manager中出现\xAC\xED\x00\x05t\x00乱码问题
查看>>
CentOS7配置Nginx服务
查看>>
Idea 提示cannot resolve symbol 无法找到类又能正常运行问题
查看>>
Invalid header signature
查看>>
Unknown column 'duration' in 'where clause'
查看>>