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

Asp.net WebAPI 单元测试

单元测试 mock EF 中DbContext 和DbSet Include

先看一下项目结构图:

Asp.net WebApi + EF   单元测试架构 DbContext一站到底

这个demo非常简单,UTWebApi.Data 是纯粹的数据定义,UTWebApi.Service是我们的业务服务逻辑层,UTWebApi 是我们webapi的实现,UTWebApi.Tests就是测试项目。

数据层:

BloggerDbContext的构造函数一般都是一个,有些时候也会有多个,如:

Asp.net WebApi + EF   单元测试架构 DbContext一站到底

如果你的DbContext包含数据库中所有的表,那么只要第一个构造函数就可以了,但是如果你的表在几个DbContext中,那么第二构造函数可能需要了, 比如你需要同时操作10张表,那么这10张表的操作应该在同一个事务里面吧,但是他们分布在2个DbContext里面,所以这2个DbContext应该用一个连接。

 internal class ArticleConfiguration : EntityTypeConfiguration<Article>实体的配置类不应该是public。

 

服务层:

我们首先需要一个基类的service如下

Asp.net WebApi + EF   单元测试架构 DbContext一站到底

当然很多项目开发的时候喜欢用Repository模式, 我这里也简单实现如下:

Asp.net WebApi + EF   单元测试架构 DbContext一站到底

而我们具体的服务实现也就很简单了   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);
        }
    }
View Code

相关文章: