文档章节

如何在单元测试时隔离ORM

zhixin9001
 zhixin9001
发布于 2017/06/01 22:01
字数 687
阅读 174
收藏 9

在项目中需要对DAL层进行单元测试,如果直接操作数据库,首先测试速度会大大下降,而且让单元测试直接使用外部依赖,很可能带来后续维护的不便,所以有必要对数据库隔离,然后单独测试DAL层。由于使用了ORM框架EF,就从EF入手。按照单元测试的思路,这是便在DAL层与EF之间找到或制造接缝,并从接缝处开始分割、注入。

 

一 基本思路

a) 有个专门的设计模式(Repository)可以解决这个问题,这种模式除了能很好的达成我目前隔离ORM以进行单元测试的目的,还允许方便地替换ORM和数据库,比如从EF换成Dapper、从SQL Server 换成MySQL。这看来是很好的方法,但有点复杂,没有弄明白。这儿是为了达到隔离ORM框架的目的,所以就借鉴Repository模式的思路,先来个简化版的,借用别人的图描述:

 

图片来源:http://www.cnblogs.com/zhaopei/p/UnitTesting.html

 

以前在DAL中直接操作EF,两者紧密耦合。拿操作Student实体来举例,重构后将EF相关的代码都封装到IStudentRepository接口后面,这样DAL中操作的是IStudentRepository接口的方法而不再是EF了,随后便可以用实现IStudentRepository接口的桩对象来替换EF了。

 

b) 具体的实现中,规定了IRepository<T>接口,这个接口定义了基本的增删改查操作

 

 

 

如果是与后台管理员相关的逻辑,AdminUserRepository会实现这个接口,Add方法如下,在这里会直接操作EF对象(FitDbContext)。

 

 

然后在AdminUserService中,将AdminUserRepository经过构造函数传入

 

 

AdminUserRepository是对EF操作的封装,因为它实现了IRepository接口,所以可以基于IRepository接口产生伪对象,而且这样的结构还允许在AdminUserRepository中实现缓存,这样来看,叫Repository真是太形象了,上层代码可以直接从仓库中拿数据,而不必关心数据是直接从数据库拿还是上次缓存的。经过这样的改造后,便可以方便地进行单元测试了。

 

 

 

 

二 隔离后的测试案例

下面是一些使用NUnit和NSubstitute的测试代码记录

a) 验证桩对象的int型返回值

 

 

b) 测试返回的IQueryable结果集

 

为了伪造IQueryable结果集花了不少功夫,最后终于知道可以用.AsQueryable()方法。

 

c) 如果要验证返回的实体是否相等,需要重写相关的Equals方法

 

在AreEqual可以指定“相等”的标准

 

© 著作权归作者所有

共有 人打赏支持
zhixin9001
粉丝 7
博文 97
码字总数 76864
作品 0
西安
加载中

评论(2)

zhixin9001
zhixin9001

引用来自“liulanghan8023”的评论

用mock不就可以了
嗯嗯,我就是记录了引入接缝以创建mock或stub的过程
流浪汉8023
流浪汉8023
用mock不就可以了
仓储(Repository)和工作单元模式(UnitOfWork)

仓储和工作单元模式 仓储模式 为什么要用仓储模式 通常不建议在业务逻辑层直接访问数据库。因为这样可能会导致如下结果: 重复的代码 编程错误的可能性更高 业务数据的弱类型 更难集中处理数...

JoeSnail
01/18
0
0
【转】事务策略: 了解事务陷阱

前沿(笔者加):事务(Transaction)是每一个与数据库有关的系统开发与设计人员都会接触到的东西,在Java中,传统的直接使用JDBC的事务开始、提交、回滚的方式已经随着各种应用开发框架(尤...

晨曦之光
2012/03/09
0
0
模拟是一种代码异味(软件编写)(第十二部分)

原文地址:Mocking is a Code Smell 原文作者:Eric Elliott 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:yoyoyohamapi 校对者:IridescentMia athena0304 (译注...

吴晓军
2017/12/10
0
0
.NET Core TDD 前传: 编写易于测试的代码 -- 缝

有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户...

solenovex
07/25
0
0
途牛原创|大话权限中心的PHP架构之道

序 权限管理是无线运营系统中的核心模块,通过访问控制策略的配置,来约定人与资源的访问关系。 本文着重讲解如何通过PHP来构建一个灵活、通用、安全的权限管理系统。 关于权限 首先我们来聊...

ftwbzhao
2016/05/12
33
0

没有更多内容

加载失败,请刷新页面

加载更多

Shiro | 实现权限验证完整版

写在前面的话 提及权限,就会想到安全,是一个十分棘手的话题。这里只是作为学校Shiro的一个记录,而不是,权限就应该这样设计之类的。 Shiro框架 1、Shiro是基于Apache开源的强大灵活的开源...

冯文议
今天
1
0
linux 系统的运行级别

运行级别 运行级别 | 含义 0 关机 1 单用户模式,可以想象为windows 的安全模式,主要用于修复系统 2 不完全的命令模式,不含NFS服务 3 完全的命令行模式,就是标准的字符界面 4 系统保留 5 ...

Linux学习笔记
今天
2
0
学习设计模式——命令模式

任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。 解决了这...

江左煤郎
今天
3
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
15
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部