Asp.net WebApi + EF 单元测试架构 DbContext一站到底
其实关于webapi和Ef service的单元测试我以前已经写过相关文章,大家可以参考:
单元测试 mock EF 中DbContext 和DbSet Include
先看一下项目结构图:
这个demo非常简单,UTWebApi.Data 是纯粹的数据定义,UTWebApi.Service是我们的业务服务逻辑层,UTWebApi 是我们webapi的实现,UTWebApi.Tests就是测试项目。
数据层:
BloggerDbContext的构造函数一般都是一个,有些时候也会有多个,如:
如果你的DbContext包含数据库中所有的表,那么只要第一个构造函数就可以了,但是如果你的表在几个DbContext中,那么第二构造函数可能需要了, 比如你需要同时操作10张表,那么这10张表的操作应该在同一个事务里面吧,但是他们分布在2个DbContext里面,所以这2个DbContext应该用一个连接。
internal class ArticleConfiguration : EntityTypeConfiguration<Article>实体的配置类不应该是public。
服务层:
我们首先需要一个基类的service如下
当然很多项目开发的时候喜欢用Repository模式, 我这里也简单实现如下:
而我们具体的服务实现也就很简单了 public ArticleService(BloggerDbContext ctx) : base(ctx) { }
webapi层:
在Asp.net WebAPI 单元测试 里面webapi的IOC 使用Unity.WebApi 对应的测试用的是Autofac.WebApi2,这次我们换成StructureMap(今天在公司尝试webapi里面用Unity,发现以前它的service也在用unity,但是以前用的是2.1,现在unity.webapi用的是5.1,所以要用unity还要改以前服务层的code,于是乎就用StructureMap)。需要开发2个帮助类:
public class StructureMapScope : IDependencyScope
{
private readonly IContainer container; public StructureMapScope(IContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
} public object GetService(Type serviceType)
{
if (serviceType == null)
{
return null;
} if (serviceType.IsAbstract || serviceType.IsInterface)
{
return this.container.TryGetInstance(serviceType);
} return this.container.GetInstance(serviceType);
} public IEnumerable<object> GetServices(Type serviceType)
{
return this.container.GetAllInstances(serviceType).Cast<object>();
} public void Dispose()
{
this.container.Dispose();
}
} public class StructureMapDependencyResolver : StructureMapScope, IDependencyResolver
{
private readonly IContainer container; public StructureMapDependencyResolver(IContainer container)
: base(container)
{
this.container = container;
} public IDependencyScope BeginScope()
{
var childContainer = this.container.GetNestedContainer();
return new StructureMapScope(childContainer);
}
}
具体使用如下:
api运行结果如图:
测试项目:
首先测试需要mock DBContext,大家可以参考单元测试 mock EF 中DbContext 和DbSet Include 来做,其次我们需要一个DbHelper,用它来货物DbContext 和初始化数据:
那么测试项目的code 也就非常简单:
看这里的测试已经通过了, 这个DbContext是所有的测试共用的,就如同我们的数据库一样,尤其是DbContext的表比较多(500以上),那么mock这个DbContext需要花费比较长的时间。
整个项目的结构就说完了,一般我们的controller的ioc都是做服务层,而服务层又需要ioc数据层,就像我前面的Asp.net WebAPI 单元测试里面的GetIArticleService方法,其实现还是比较累的,太多的mock了,
同时在controller那里的ioc 的code也就比较多了,每增加一个controller就需要增加一个对应的service,那么ioc对应的配置也要增加 是不是很麻烦了? 所以索性直接ioc DbContext。因为在我们很多实际项目中service中的code 重用性不是很高,每当增加controller的时候,一般都要增加service去实现相应的逻辑,比如一个查询逻辑现在有3个service已经实现了,但是在controller你可能不直接用这3个service, 而是重新建一个service,把3个EF 查询合并成一个,这样EF访问3次DB 就变为一次,并且不需要的数据也不会返回了。所以这里的DbContext真的是一站到底, 从数据层经过服务层最后坚持到接口层,而单元测试的难点就在如何mock DbContext,这里我们采用万剑归中的方式来做(表达式给DbContext的DbSet赋值)。
Asp.net WebApi + EF 单元测试架构 DbContext一站到底的更多相关文章
- 转载——Asp.Net MVC+EF+三层架构的完整搭建过程
转载http://www.cnblogs.com/zzqvq/p/5816091.html Asp.Net MVC+EF+三层架构的完整搭建过程 架构图: 使用的数据库: 一张公司的员工信息表,测试数 ...
- Asp.Net WebApi 使用OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联(No OWIN authentication manager is associated with the request)” 异常的解决办法
在Asp.Net WebApi 项目中使用OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. ...
- Asp.Net MVC+EF+三层架构的完整搭建过程
架构图: 使用的数据库: 一张公司的员工信息表,测试数据 解决方案项目设计: 1.新建一个空白解决方案名称为Company 2.在该解决方案下,新建解决方案文件夹(UI,BLL,DAL,Model) ...
- Asp.Net MVC+EF+三层架构
架构图: 使用的数据库: 一张公司的员工信息表,测试数据 解决方案项目设计: 1.新建一个空白解决方案名称为Company 2.在该解决方案下,新建解决方案文件夹(UI,BLL,DAL,Model) ...
- [转]ASP.NET MVC3 + EF 性能优化解决方案以及最优架构
[集思广议] 我们用 asp.net mvc3 + ef 做了一个网站,现在是内测阶段,发现打开速度非常慢.首页打开(无缓存)都在5-6s以上(测试环境:程序和db都在本机),请问各位 mv ...
- Asp.net WebAPI 单元测试
现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要.一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试.对下层的依赖我们通过IOC ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...
- Asp.Net WebApi 调试利器“单元测试”
当我们编辑好一个WebApi应用程序后,需要对该Api接口进行调试,传统的调试办法是在方法内设置断点,然后用PostMan等http工具模拟访问进行查看WebAPI的运行情况,但这种除了效率较低还进行 ...
- OData – the best way to REST–实例讲解ASP.NET WebAPI OData (V4) Service & Client
一.概念介绍 1.1,什么是OData? 还是看OData官网的简单说明: An open protocol to allow the creation and consumption of quer ...
随机推荐
- iOS中POST异步请求
POST异步请求(代理) 1.遵循<NSURLConnectionDataDelegate> @interface ViewController ()<NSURLConnection ...
- poi管道流的导入导出
/** * 导入学生信息 * * @param classid * @param uploadFilePath * @return */ public boolean uploadStudentFil ...
- [python] 线程池
特别感谢simomo 什么是线程池? 诸如web服务器.数据库服务器.文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务.构建服务器应用程序的一个过于简单的模型是:每当一 ...
- linq 多条件查询
Linq 进行多条件查询的时候使用PredicateBuilder帮助类可以很好的解决. 类的源码: public static class PredicateBuilder { /// <su ...
- 使用my exclipse对数据库进行操作(1)
一.查找 public class class1 { public static void main(String[] args) { // TODO Auto-generated method st ...
- 树状DP (poj 2342)
题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...
- C#开发中使用Npoi操作excel实例代码
C#开发中使用Npoi操作excel实例代码 出处:西西整理 作者:西西 日期:2012/11/16 9:35:50 [大 中 小] 评论: 0 | 我要发表看法 Npoi 是什么? 1.整个Exce ...
- processing学习笔记
这是从http://funprogramming.org/视频学习过程中做的笔记,没法看视频的话,请FQ 点point(x,y); 线line(x,y,x2,y2); 背景background(x), ...
- struts2的运行原理及配置文件
struts2官方运行原理图: 1,客户发送请求(url地址就是请求),tomcat接到请求会找到相应的应用web.xml配置文件. 2,web.xml中filter拦截器把你的请求接收到,并进入Fi ...
- poj 3613 经过k条边最短路 floyd+矩阵快速幂
http://poj.org/problem?id=3613 s->t上经过k条边的最短路 先把1000范围的点离散化到200中,然后使用最短路可以使用floyd,由于求的是经过k条路的最短路, ...