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 ...
随机推荐
- eclipse maven项目错误
eclipse maven项目错误:Failure to transfer org.codehaus.plexus:plexus-interpolation:jar:1.15 from http:// ...
- bootstrapvalidator+bootstrap-select select无法校验问题解决方法
$("#form_user_input") .bootstrapValidator( { message : 'This value is not valid', excluded ...
- NPOI导出Excel (C#) 踩坑 之--The maximum column width for an individual cell is 255 charaters
/******************************************************************* * 版权所有: * 类 名 称:ExcelHelper * 作 ...
- 调用Interop.zkemkeeper.dll无法使用解决方案
调用Interop.zkemkeeper.dll无法使用 已经注册dll成功但是还是报错 检索 COM 类工厂中 CLSID 为 {00853A19-BD51-419B--2DABE57EB61F} ...
- IntelliJ IDEA mac 快捷键
cmd+O 查找类alt+cmd+O 符号shift+cmd+O 查找文件^+space 补全alt + F7 查找符号的使用情况F1 查看文档cmd+b 跳转定义,或者 鼠标+ctrlcmd+F12 ...
- 每天写点shell——read的用法
1.read基本读取 #!/bin/bash #testing the read command echo -n "Enter you name:" #echo -n 让用户直接在 ...
- java时间类型操作
java中Date类型与字符串相互转化 Date date = new Date(); System.out.println(date); //DateFormat类为一个 ...
- Velocity 局部定制模板
Velocity介绍 Velocity是一个基于java的template engine.它允许Web designer引用Java Code中定义的方法.Web designer可以和Java工程师 ...
- [Hadoop] Hadoop学习历程 [持续更新中…]
1. Hadoop FS Shell Hadoop之所以可以实现分布式计算,主要的原因之一是因为其背后的分布式文件系统(HDFS).所以,对于Hadoop的文件操作需要有一套全新的shell指令来完成 ...
- 使用stack的思考
对于使用stack进行()的配对检查,不需要使用额外的空间对每个字符进行存储和push与pop的操作. 只使用size对()进行处理即可,因为只有一种括号,所以入栈为size加1,出栈为size-1. ...