其实关于webapi和Ef service的单元测试我以前已经写过相关文章,大家可以参考:

Asp.net WebAPI 单元测试

单元测试 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一站到底的更多相关文章

  1. 转载——Asp.Net MVC+EF+三层架构的完整搭建过程

    转载http://www.cnblogs.com/zzqvq/p/5816091.html Asp.Net MVC+EF+三层架构的完整搭建过程 架构图: 使用的数据库: 一张公司的员工信息表,测试数 ...

  2. Asp.Net WebApi 使用OWIN架构后,出现 “没有 OWIN 身份验证管理器与此请求相关联(No OWIN authentication manager is associated with the request)” 异常的解决办法

    在Asp.Net WebApi 项目中使用OWIN模块之后,如果没有在OWIN的Startup类中配置认证方式,调用WebApi的相关Controller和Action就会出现如下异常: 出现错误. ...

  3. Asp.Net MVC+EF+三层架构的完整搭建过程

    架构图: 使用的数据库: 一张公司的员工信息表,测试数据 解决方案项目设计: 1.新建一个空白解决方案名称为Company 2.在该解决方案下,新建解决方案文件夹(UI,BLL,DAL,Model) ...

  4. Asp.Net MVC+EF+三层架构

    架构图: 使用的数据库: 一张公司的员工信息表,测试数据 解决方案项目设计: 1.新建一个空白解决方案名称为Company 2.在该解决方案下,新建解决方案文件夹(UI,BLL,DAL,Model) ...

  5. [转]ASP.NET MVC3 + EF 性能优化解决方案以及最优架构

    [集思广议]      我们用 asp.net mvc3 + ef 做了一个网站,现在是内测阶段,发现打开速度非常慢.首页打开(无缓存)都在5-6s以上(测试环境:程序和db都在本机),请问各位 mv ...

  6. Asp.net WebAPI 单元测试

    现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要.一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试.对下层的依赖我们通过IOC ...

  7. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) ...

  8. Asp.Net WebApi 调试利器“单元测试”

    当我们编辑好一个WebApi应用程序后,需要对该Api接口进行调试,传统的调试办法是在方法内设置断点,然后用PostMan等http工具模拟访问进行查看WebAPI的运行情况,但这种除了效率较低还进行 ...

  9. 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 ...

随机推荐

  1. each函数

  2. oracle 多级菜单查询 。start with connect by prior

    select * from S_dept where CODE in(select sd.code from s_dept sd start with sd.code='GDKB' connect b ...

  3. Browser增加下载路径选择功能

    SWE Browser中有xml/download_settings_preferences.xml, 但在代码中却没有调用,导致“设置”中没有”选择下载路径“功能. 在com.android.bro ...

  4. 解决AndroidADT自带Eclipse编辑器不能自动代码提示的问题

    今天发现,我下载的AndroidADT开发套装中自带的Eclipse没有自动代码提示功能.通过参考http://blog.csdn.net/coolszy/article/details/724195 ...

  5. Reduce inversion count 求最小逆序数

    本问题出自:微软2014实习生及秋令营技术类职位在线测试 (Microsoft Online Test for Core Technical Positions) Description Find a ...

  6. <转载> OpenGL Projection Matrix

    原文 OpenGL Projection Matrix Related Topics: OpenGL Transformation Overview Perspective Projection Or ...

  7. coocs2d-x资源压缩笔记

    使用 texturepacker 压缩: 如下设置,主要设置红框里面的,其他默认即可 上面设置的关键是 texture format 必须是 pvr.ccz,如果是png的话,下面的 img form ...

  8. office2003-2007 绿色版 出错 文件丢失(未解决)

    - 这个版本是我大学时候(2012)年一直用到现在的版本:目录结构如下: 原来一直在32位系统中使用,没有出错过; - 刚装的两台电脑系统分别为 Win7Pro 和 Win10Pro ,都是64位的: ...

  9. Capistrano初探--Ruby快速部署工具

    1.Capistrano介绍 是什么?---一种部署工具.(部署就是在生产服务器上安装应用程序,或是更新最新版本:web服务器的启动重启与停止:使网站进入维护状态或将其恢复为常态) 在进行 Rails ...

  10. 【整理】--VC 编译整理

    .h用于编译阶段的审核,如在math.h中有函数声明:int abs(int);但是在使用中写为#include <math.h>...abs(3,5);编译器阶段就会检测出错误. .dl ...