ABP中单元测试的技巧:Mock和数据驱动
(此文章同时发表在本人微信公众号“dotNET每日精华文章”,欢迎右边二维码来关注。)
题记:虽然ABP为大家提供了测试的脚手架了,不过有些小技巧还是需要自己探索的。
ASP.NET Boilerplate(ABP)默认使用的单元测试的框架是xUnit,并且引入了NSubstitute这个便捷的Mock框架。但是有些具体的用法和技巧还是需要自己探索的。下面介绍两个小技巧。
为AppService注入Mock接口
假设我有一个和钉钉相关的AppService(接口名称为IDingtalkAppService),这个服务中会调用钉钉的sdk,为了在单元测试的时候避免真实的网络调用,所以我需要把这部分代码抽象为一个接口(比如名称为IDingtalkSdkService)。那么如何把IDingtalkSdkService 模拟注入到IDingtalkAppService中呢?
首先,在TestModule的PreInitialize中添加如下代码:
//Registering fake services
IocManager.IocContainer.Register(
Component.For<IAbpZeroDbMigrator>()
.UsingFactoryMethod(() => Substitute.For<IAbpZeroDbMigrator>())
.LifestyleSingleton(),
Component.For<IDingtalkSdkService>()
.UsingFactoryMethod(() => Substitute.For<IDingtalkSdkService>())
.LifestyleSingleton()
);
上面的代码通过NSubstitute为IDingtalkSdkService注册一个Mock。在测试类中,还是如ABP的惯例那样,通过Resolve来获取IDingtalkAppService的实现。只是在需要给Mock接口的方法设置Returns数据的时候,在测试方法中通过Resolve来现时获取到此接口的实例。如下:
var sdkService = Resolve<IDingtalkSdkService>();
sdkService.GetAllUserList(null, enterprise).Returns(
这种方式虽然最简单但有个缺陷,就是必须注册的时候要求注册为LifestyleSingleton(单例)。那么如果你依赖的外部接口无法以单例模式运行(这种情况应该极少),那么只有给IDingtalkAppService添加一个IDingtalkSdkService的属性SdkService,然后把上面的代码替换为appService.SdkService.GetAllUserList。
NSubstitute使用的更多帮助,请参考其官网:http://nsubstitute.github.io/
数据驱动的单元测试
准确说这不属于ABP的技巧是xUnit的技巧,只是ABP用到了xUnit,就一并提及。我们的业务逻辑可能会涉及到多个场景或者判断条件,为了测试每种情况,是为每种情况写一个测试方法并包含大量的重复代码,还是使用数据驱动注入测试数据到一个测试方法中,显然最好的方式是后者。
常见的单元测试框架都提供了数据驱动的支持:
- xUnit:http://www.tomdupont.net/2012/04/xunit-theory-data-driven-unit-test.html
- NUnit:http://www.tomdupont.net/2014/06/nunit-testcase-data-driven-unit-test.html
- MSTest:https://msdn.microsoft.com/en-us/library/ms182527.aspx
就我的感受而言,xUnit处理数据驱动的方式更为自然。我采用了MemberData的方式来提供数据,就是写一个返回值为IEnumerable<object[]>的静态公共方法。
“不废话,直接上代码”,大家更能一目了然。示例代码见:http://git.oschina.net/ike/xbonmpl9wav062rsj71y872.code.git
通过这种方式,我检查出了一个判断错误,如下图:

ABP中单元测试的技巧:Mock和数据驱动的更多相关文章
- 在eclipse中使用JUnit4,以及使用JUnit4进行单元测试的技巧
一 在eclipse中使用JUnit4 首先在工程上右键,选择属性,找到Java Builder Path,添加JUnit4的lib,如下图: 在要测试的类上右键新建 Junit test cas ...
- ABP中的依赖注入思想
在充分理解整个ABP系统架构之前首先必须充分了解ABP中最重要的依赖注入思想,在后面会具体举出一些实例来帮助你充分了解ABP中的依赖注入思想,在了解这个之前我们首先来看看什么是依赖注入?来看看维基百科 ...
- ABP中使用Redis Cache(2)
上一篇讲解了如何在ABP中使用Redis Cache,虽然能够正常的访问Redis,但是Redis里的信息无法同步更新.本文将讲解如何实现Redis Cache与实体同步更新.要实现数据的同步更新,我 ...
- 原!!关于java 单元测试Junit4和Mock的一些总结
最近项目有在写java代码的单元测试,然后在思考一个问题,为什么要写单元测试??单元测试写了有什么用??百度了一圈,如下: 软件质量最简单.最有效的保证: 是目标代码最清晰.最有效的文档: 可以优化目 ...
- ABP源码分析二:ABP中配置的注册和初始化
一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...
- ABP源码分析三十五:ABP中动态WebAPI原理解析
动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...
- ABP源码分析四十七:ABP中的异常处理
ABP 中异常处理的思路是很清晰的.一共五种类型的异常类. AbpInitializationException用于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationExce ...
- ios开发中的小技巧
在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIViewal ...
- 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧
[源码下载] 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 作者:webabcd 介绍背水一战 Wind ...
随机推荐
- 使用django开发博客过程记录5——日期归档和视图重写
针对每条博客的观看次数我么是使用django的Mixin实现的: def get(self, request, *args, **kwargs): last_visit = request.sessi ...
- MVC重定向-自定义路由篇
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.Ignore ...
- 大神php摘录
1. $rs = M('order')->where('id='.$res['id'])->save($order); )){ M('member')->where('id='.$m ...
- Apache Shiro 学习记录4
今天看了教程的第三章...是关于授权的......和以前一样.....自己也研究了下....我觉得看那篇教程怎么说呢.....总体上是为数不多的精品教程了吧....但是有些地方确实是讲的太少了.... ...
- 2016百度之星 资格赛ABCDE
看题:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690 交题:http://acm.hdu.edu.cn/search.php ...
- 最长回文子串(Longest Palindromic Substring)
这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...
- CSS 高级布局技巧
随着 IE8 逐渐退出舞台,很多高级的 CSS 特性都已被浏览器原生支持,再不学下就要过时了. 用 :empty 区分空元素 兼容性:不支持 IE8 /*假如我们有以上列表:*/ <div cl ...
- vim 编辑器的光标操作
vim中最简单的移动光标的方式是使用使用方向键操作,但这种方式的效率底下,更高效的方式是使用快捷键,常用的快捷键如下表所示. 快捷键 功 ...
- Alpha版总结会议
昨天上课的时候,我们学习了项目总结这一部分的内容,并根据老师提供的项目Postmortem模板对我们的项目进行了总结. 项目Postmortem模板主要分为设想和目标.计划.资源.变更管理.设计和实现 ...
- rails数据库查询 N + 1 查询的解决办法
schema.rb ActiveRecord::Schema.define(version: 20150203032005) do create_table "addresses" ...