博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Entity Framework 实体框架的形成之旅--为基础类库接口增加单元测试,对基类接口进行正确性校验(10)...
阅读量:5244 次
发布时间:2019-06-14

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

本篇介绍Entity Framework 实体框架的文章已经到了第十篇了,对实体框架的各个分层以及基类的封装管理,已经臻于完善,为了方便对基类接口的正确性校验,以及方便对以后完善或扩展接口进行回归测试,那么建立单元测试就有很大的必要,本篇主要介绍如何利用VS创建内置的单元测试项目进行实体框架的基类接口测试。

在采用单元测试这个事情上,很多人可能想到了NUnit单元测试工具和NMock工具进行处理,其实微软VS里面也已经为我们提供了类似的单元测试工具了,可以不需要使用这个第三方的单元测试工具,经试用VS的单元测试工具还是整合性很好,使用非常方便的。

1、实体框架架构及基础类库接口

 在上次的随笔《》里面,我根据实体框架中混合模式的框架结构,所涉及的架构图形如下所示。

我们从上图可以看到,整个框架从下往上分为了几个明显的层次,一个数据访问层DAL层,一个是业务逻辑层BLL层,一个是Facade门面层,各个层的功能不同,这几个层中以DAL层最为复杂一些,涉及到底层多种数据库的抽象实现,由于Entity Framework 实体框架本身就是对多种数据库的实现抽象,因此本文重点针对这个DAL层进行单元测试。

其中的实体框架的公用类库(WHC.Framework.EF),里面涉及到的IBaseDAL就是数据访问层的基类接口,具体数据访问的抽象实现就在BaseDAL的基类上。

在IBaseDAL接口里面,定义了很多我们数据访问类需要使用的增删改查、分页、统计、辅助方法等接口,以及各个方法的异步方法接口,如下所示。

namespace WHC.Framework.EF{    ///     /// 数据访问层基类接口    ///     /// 
实体对象类型
public interface IBaseDAL
where T : class { #region 对象添加、修改、删除 ///
/// 插入指定对象到数据库中 /// ///
指定的对象 ///
执行成功返回
true
,否则为
false
bool Insert(T t); ///
/// 插入指定对象到数据库中(异步) /// ///
指定的对象 ///
执行成功返回
true
,否则为
false
Task
InsertAsync(T t); ///
/// 插入指定对象集合到数据库中 /// ///
指定的对象集合 ///
执行成功返回
true
,否则为
false
bool InsertRange(IEnumerable
list); ///
/// 插入指定对象集合到数据库中(异步) /// ///
指定的对象集合 ///
执行成功返回
true
,否则为
false
Task
InsertRangeAsync(IEnumerable
list); ///
/// 更新对象属性到数据库中 /// ///
指定的对象 ///
主键的值 ///
执行成功返回
true
,否则为
false
bool Update(T t, object key); ///
/// 更新对象属性到数据库中(异步) /// ///
指定的对象 ///
主键的值 ///
执行成功返回
true
,否则为
false
Task
UpdateAsync(T t, object key); ///
/// 根据指定对象的ID,从数据库中删除指定对象 /// ///
对象的ID ///
执行成功返回
true
,否则为
false
bool Delete(object id); ///
/// 根据指定对象的ID,从数据库中删除指定对象(异步) /// ///
对象的ID ///
执行成功返回
true
,否则为
false
Task
DeleteAsync(object id); ///
/// 从数据库中删除指定对象 /// ///
指定对象 ///
执行成功返回
true
,否则为
false
bool Delete(T t); ///
/// 从数据库中删除指定对象(异步) /// ///
指定对象 ///
执行成功返回
true
,否则为
false
Task
DeleteAsync(T t); ///
/// 根据指定条件,从数据库中删除指定对象 /// ///
条件表达式 ///
执行成功返回
true
,否则为
false
bool DeleteByExpression(Expression
> match); ///
/// 根据指定条件,从数据库中删除指定对象(异步) /// ///
条件表达式 ///
执行成功返回
true
,否则为
false
Task
DeleteByExpressionAsync(Expression
> match); ///
/// 根据指定条件,从数据库中删除指定对象 /// ///
删除记录的条件语句 ///
执行成功返回
true
,否则为
false
bool DeleteByCondition(string condition); ///
/// 根据指定条件,从数据库中删除指定对象(异步) /// ///
删除记录的条件语句 ///
执行成功返回
true
,否则为
false
Task
DeleteByConditionAsync(string condition); #endregion

或者一些其他的分页等复杂的实现接口。

#region 返回集合的接口        ///         /// 返回可查询的记录源        ///         /// 
IQueryable
GetQueryable(); ///
/// 根据条件表达式返回可查询的记录源 /// ///
查询条件 ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
IQueryable
GetQueryable(Expression
> match, string sortPropertyName, bool isDescending = true); ///
/// 根据条件表达式返回可查询的记录源 /// ///
查询条件 ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
IQueryable
GetQueryable
(Expression
> match, Expression
> orderByProperty, bool isDescending = true); ///
/// 返回数据库所有的对象集合 /// ///
IList
GetAll(); ///
/// 返回数据库所有的对象集合(异步) /// ///
Task
> GetAllAsync(); ///
/// 返回数据库所有的对象集合 /// ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
IList
GetAll
(Expression
> orderByProperty, bool isDescending = true); ///
/// 返回数据库所有的对象集合(异步) /// ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
Task
> GetAllAsync
(Expression
> orderByProperty, bool isDescending = true); ///
/// 返回数据库所有的对象集合(用于分页数据显示) /// ///
条件表达式 ///
分页实体 ///
指定对象的集合
IList
GetAllWithPager(PagerInfo info); ///
/// 返回数据库所有的对象集合(用于分页数据显示,异步) /// ///
分页实体 ///
指定对象的集合
Task
> GetAllWithPagerAsync(PagerInfo info); ///
/// 根据条件查询数据库,并返回对象集合 /// ///
条件表达式 ///
IList
Find(Expression
> match); ///
/// 根据条件查询数据库,并返回对象集合(异步) /// ///
条件表达式 ///
Task
> FindAsync(Expression
> match); ///
/// 根据条件查询数据库,并返回对象集合 /// ///
条件表达式 ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
IList
Find
(Expression
> match, Expression
> orderByProperty, bool isDescending = true); ///
/// 根据条件查询数据库,并返回对象集合(异步) /// ///
条件表达式 ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
Task
> FindAsync
(Expression
> match, Expression
> orderByProperty, bool isDescending = true); ///
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示) /// ///
条件表达式 ///
分页实体 ///
指定对象的集合
IList
FindWithPager(Expression
> match, PagerInfo info); ///
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示,异步) /// ///
条件表达式 ///
分页实体 ///
指定对象的集合
Task
> FindWithPagerAsync(Expression
> match, PagerInfo info); ///
/// 根据条件查询数据库,并返回对象集合(用于分页数据显示) /// ///
条件表达式 ///
分页实体 ///
排序表达式 ///
如果为true则为降序,否则为升序 ///
指定对象的集合
IList
FindWithPager
(Expression
> match, PagerInfo info, Expression
> orderByProperty, bool isDescending = true); #endregion

以及更多的方法接口,我们为了校验没有接口都能够正常工作,就需要对它们进行单元测试。

 

2、在VS里面创建单元测试项目及编写单元测试代码

在VS里面创建内置的单元测试项目如下所示,在添加新项目里面选择测试->单元测试项目即可,如下图所示。

为了方便对基类测试,我们还是需要创建一个简单的代表性数据库用来检查基础的接口操作。

由于前面的系列,已经介绍过了,我们在构建数据访问层的时候,使用的是基于IOC的方式构建一个对象的接口对象,如这样代码IFactory.Instance<IUserDAL>()所示。

而单元测试,基本原理就是我们调用接口,并获取对应的输出结果,和我们预期的值进行对比,如果吻合就是正常通过的测试用例。

为了进行基础类库的单元测试,我们需要根据实体框架的结构搭建一个具体表的对象项目工程,这个采用代码生成工具Database2Sharp进行生成就可以了,生成的处理操作如下所示。

这样根据表快速生成的整个实体框架,就是我们所需要的实体框架项目,具体效果如下所示。

例如我们创建一个查找记录的单元测试方法代码如下所示。

namespace TestFrameworkEF{    [TestClass]    public class TestBaseDAL     {        private string userId = Guid.NewGuid().ToString();        [TestInitialize]        public void Init()        {            User user = new User() { ID = userId, Account = "Nunit", Password = "Nunit" };            bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); } [TestCleanup] public void Cleanup() { bool result = IFactory.Instance
().Delete(userId); Assert.AreEqual(result, true); } [TestMethod] public void FindByID() { User user = IFactory.Instance
().FindByID(userId); Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); }

其中上面红色代码部分就是单元测试的各种标识,包括单元测试类标识,以及初始化、退出清除、测试用例的标识。

上面案例,我们是在单元测试前,在数据库写入一条记录,然后在进行各种单元测试用例的运行及校验,最后退出的时候,清除我们写入的记录。

而记录的更新和删除接口,我们具体的单元测试代码如下所示。

[TestMethod]        public void Update()        {            string newAccount = "Test";            User user = IFactory.Instance
().FindByID(userId); user.Account = newAccount; bool result = IFactory.Instance
().Update(user, user.ID); Assert.AreEqual(result, true); user = IFactory.Instance
().FindByID(userId); Assert.IsNotNull(user); Assert.AreEqual(user.Account, newAccount); } [TestMethod] public void Delete() { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" }; bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); result = IFactory.Instance
().Delete(id); Assert.AreEqual(result, true); }

 

最后我们整个单元测试的测试代码如下所示。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using WHC.Framework.EF;using EFCore.IDAL;using EFCore.Entity;using Microsoft.VisualStudio.TestTools.UnitTesting;using System.Linq.Expressions;using System.Linq;using WHC.Pager.Entity;namespace TestFrameworkEF{    [TestClass]    public class TestBaseDAL     {        private string userId = Guid.NewGuid().ToString();        [TestInitialize]        public void Init()        {            User user = new User() { ID = userId, Account = "Nunit", Password = "Nunit" };            bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); } [TestCleanup] public void Cleanup() { bool result = IFactory.Instance
().Delete(userId); Assert.AreEqual(result, true); } [TestMethod] public void FindByID() { User user = IFactory.Instance
().FindByID(userId); Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void Insert() { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id , Account = "Nunit", Password = "Nunit" }; bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); user = IFactory.Instance
().FindByID(id); Assert.IsNotNull(user); Assert.AreEqual(user.ID, id); result = IFactory.Instance
().Delete(id); Assert.AreEqual(result, true); } [TestMethod] public void InsertRang() { List
list = new List
(); for(int i = 0; i<3; i++) { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id, Account = "Nunit" + i.ToString(), Password = "Nunit" }; list.Add(user); } bool result = IFactory.Instance
().InsertRange(list); Assert.AreEqual(result, true); foreach(User user in list) { result = IFactory.Instance
().Delete(user.ID); Assert.AreEqual(result, true); } } [TestMethod] public void Update() { string newAccount = "Test"; User user = IFactory.Instance
().FindByID(userId); user.Account = newAccount; bool result = IFactory.Instance
().Update(user, user.ID); Assert.AreEqual(result, true); user = IFactory.Instance
().FindByID(userId); Assert.IsNotNull(user); Assert.AreEqual(user.Account, newAccount); } [TestMethod] public void Delete() { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" }; bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); result = IFactory.Instance
().Delete(id); Assert.AreEqual(result, true); } [TestMethod] public void DeleteByExpression() { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" }; bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); Expression
> expression = p => p.ID == user.ID && p.Account == user.Account; result = IFactory.Instance
().DeleteByExpression(expression); Assert.AreEqual(result, true); } [TestMethod] public void DeleteByCondition() { var id = Guid.NewGuid().ToString(); User user = new User() { ID = id, Account = "Nunit", Password = "Nunit" }; bool result = IFactory.Instance
().Insert(user); Assert.AreEqual(result, true); string condition = string.Format("ID ='{0}' ", id); result = IFactory.Instance
().DeleteByCondition(condition); Assert.AreEqual(result, true); } [TestMethod] public void FindSingle() { Expression
> expression = p => p.ID == userId; User dbUser = IFactory.Instance
().FindSingle(expression); Assert.IsNotNull(dbUser); Assert.AreEqual(dbUser.ID, userId); } [TestMethod] public void GetQueryable() { User user = IFactory.Instance
().GetQueryable().Take(1).ToList()[0]; Assert.IsNotNull(user); //Assert.AreEqual(user.ID, userId); } [TestMethod] public void GetQueryableExpression() { Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().GetQueryable(expression, "Account").Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void GetQueryableExpression2() { Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().GetQueryable(expression, s=>s.Account).Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void GetAll() { User user = IFactory.Instance
().GetAll().Take(1).ToList()[0]; Assert.IsNotNull(user); } [TestMethod] public void GetAllOrderBy() { User user = IFactory.Instance
().GetAll(s=>s.Account).Take(1).ToList()[0]; Assert.IsNotNull(user); } [TestMethod] public void GetAllWithPager() { PagerInfo pagerInfo = new PagerInfo(); pagerInfo.PageSize = 30; User user = IFactory.Instance
().GetAllWithPager(pagerInfo).Take(1).ToList()[0]; Assert.IsNotNull(user); } [TestMethod] public void Find() { Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().Find(expression).Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void Find2() { Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().Find(expression, s=>s.Account).Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void FindWithPager() { PagerInfo pagerInfo = new PagerInfo(); pagerInfo.PageSize = 30; Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().FindWithPager(expression, pagerInfo).Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void FindWithPager2() { PagerInfo pagerInfo = new PagerInfo(); pagerInfo.PageSize = 30; Expression
> expression = p => p.ID == userId; User user = IFactory.Instance
().FindWithPager(expression, pagerInfo, s=>s.Account).Take(1).ToList()[0]; Assert.IsNotNull(user); Assert.AreEqual(user.ID, userId); } [TestMethod] public void GetRecordCount() { int count = IFactory.Instance
().GetRecordCount(); Assert.AreNotEqual(count, 0); } [TestMethod] public void GetRecordCount2() { Expression
> expression = p => p.ID == userId; int count = IFactory.Instance
().GetRecordCount(expression); Assert.AreNotEqual(count, 0); } [TestMethod] public void IsExistRecord() { bool result = IFactory.Instance
().IsExistRecord(userId); Assert.AreEqual(result, true); } [TestMethod] public void IsExistRecord2() { Expression
> expression = p => p.ID == userId; bool result = IFactory.Instance
().IsExistRecord(expression); Assert.AreEqual(result, true); } [TestMethod] public void SqlExecute() { string newAccount = "newAccount"; string sql = string.Format("update [User] set Account='{0}' Where ID='{1}' ", newAccount, userId); int count = IFactory.Instance
().SqlExecute(sql); Assert.AreEqual(count, 1); } [TestMethod] public void SqlValueList() { string sql = string.Format("Select ID From [User] "); ICollection
valueString = IFactory.Instance
().SqlValueList(sql); Assert.IsNotNull(valueString); Assert.IsTrue(valueString.Count > 0); } }}

3、运行单元测试

代码编译没有问题后,我们需要检验我们的单元测试代码的正确性,那么只需要在VS的测试菜单里面,执行下面的操作即可。

最后得到的运行结果如下所示,验证了我们基类代码的正确性。

 

转载于:https://www.cnblogs.com/wuhuacong/p/4584307.html

你可能感兴趣的文章
Springboot-日志框架
查看>>
P1192-台阶问题
查看>>
一、使用pip安装Python包
查看>>
spring与quartz整合
查看>>
Kattis之旅——Eight Queens
查看>>
3.PHP 教程_PHP 语法
查看>>
Duilib扩展《01》— 双击、右键消息扩展
查看>>
利用Fiddler拦截接口请求并篡改数据
查看>>
python习题:unittest参数化-数据从文件或excel中读取
查看>>
在工程中要加入新的错误弹出方法
查看>>
PS 滤镜— — sparkle 效果
查看>>
snmpwalk命令常用方法总结
查看>>
网站产品设计
查看>>
代理ARP
查看>>
go 学习笔记(4) ---项目结构
查看>>
java中静态代码块的用法 static用法详解
查看>>
Java线程面试题
查看>>
Paper Reading: Relation Networks for Object Detection
查看>>
day22 01 初识面向对象----简单的人狗大战小游戏
查看>>
mybatis源代码分析:深入了解mybatis延迟加载机制
查看>>