如何使用Moq&来模拟实体框架6自动固定 [英] How to mockup Entity Framework 6 With Moq & Autofixture

查看:76
本文介绍了如何使用Moq&来模拟实体框架6自动固定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 AutoMoq ,但是我有点困惑如何编写我的第一个单元测试由于实体框架(首先使用EF6和代码)的原因dbContext

I am using AutoMoq but I am kinda confused how to write my first unit test because of Entity Framework's (using EF6 and code first) dbContext

// in service class(constructor)
private readonly MyContext context;

public PriceService(MyContext context)
{
    this.context = context;
}

// following would be in nunit test method.
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var priceService = fixture.Create<PriceService>();

当我运行单元测试时,它崩溃了

When I run the unit test it crashes


    at Ploeh.AutoFixture.Kernel.TerminatingSpecimenBuilder.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.AutoPropertiesCommand`1.Execute(Object specimen, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.MethodInvoker.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b)
    at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
    at System.Linq.Enumerable.d__a5`1.MoveNext()
    at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
    at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
    at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context, T seed)
    at Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext context)
    at PriceServiceTests.Test_Price_Object_Setup() in PriceServiceTests.cs:line 26

编辑

在EF 6中,似乎他们使DbSet更具可模拟性.

In EF 6 seems like they are making the DbSet more mockable.

https://entityframework. codeplex.com/wikipage?title=Design%20Meeting%20Notes%20-%20May%2016%2c%202013

使DbSet更具可仿真性

Make DbSet more mockable

  • 这意味着添加受保护的构造函数并使方法虚拟化
  • 请注意,使用受保护的构造函数从DbSet派生的类型将创建一个不受任何上下文约束的对象,并且方法将为无操作.从创建测试双打的角度来看,这使其非常类似于IDbSet.
  • 如果采用此选项,我们可能会淘汰IDbSet
  • 值得注意的是,没有发现与使用IDbSet进行两次测试在功能上有所不同的案例.但是,在社区中有一种强烈的感觉,那就是首选接口.
  • These means adding a protected constructor and making methods virtual
  • Note that a type derived from DbSet that uses the protected constructor would create an object not be bound to any context and the methods would be no-ops. This makes it very like IDbSet from the perspective of creating test doubles.
  • If we took this option we could potentially obsolete IDbSet
  • It’s worth noting that no cases have been identified where this would be functionally different to using IDbSet for test doubles. However, there is strong feeling in the community that interfaces are preferred.

有人知道如何模拟吗?

编辑2

我发现了本文,但它一直崩溃

I found this article but it keeps crashing

public class MyContext : DbContext
{
    //public GroceryListContext()
    //    : base()
    //{

    //}
    public virtual DbSet<Price> Prices { get; set; }
}

[Test]
public void Test_Price_Object_Setup_Properly()
{
    var mockContext = new Mock<MyContext>();

    var mockSet = new Mock<DbSet<Price>>(); // had to add EF to my test solution.
    mockContext.Setup(m => m.Prices).Returns(mockSet.Object);
    var service = new PriceService(mockContext.Object);

    // dies when using autofixture so thought try first moq like in article
   //var priceService = fixture.Create<PriceService>();

   Assert.That(true, Is.EqualTo(false));
}

,但以下情况除外:

MyContext.Tests.Services.PriceServiceTests.Test_If_Price_Object_Setup_Properly:System.ArgumentException : Type to mock must be an interface or an abstract or non-sealed class. ----> System.TypeLoadException : Method 'Create' on type 'DbSet 1Proxyb409fc6b430b4568aac048b60ea2f02e'来自程序集"DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = a621a9e7e5方法的隐式类型试图覆盖的方法.

MyContext.Tests.Services.PriceServiceTests.Test_If_Price_Object_Setup_Properly: System.ArgumentException : Type to mock must be an interface or an abstract or non-sealed class. ----> System.TypeLoadException : Method 'Create' on type 'DbSet1Proxyb409fc6b430b4568aac048b60ea2f02e' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' tried to implicitly override a method with weaker type parameter constraints`.

推荐答案

您需要提供规范表示应模拟DbSet<T>类(尽管它不是抽象类型或接口).

You need to supply a specification which indicates that the DbSet<T> class should be mocked (although it's not an abstract type or interface).

之所以这样做,是因为DbSet<T>类是公共的,但是它具有受受保护的构造函数.

The reason for that is because the DbSet<T> class is public but it has a protected constructor.

规格:

internal class DbSetTypeSpecification : IRequestSpecification
{
    public bool IsSatisfiedBy(object request)
    {
        var type = request as Type;
        if (type == null)
            return false;

        return type.IsGenericType
            && typeof(DbSet<>) == type.GetGenericTypeDefinition();
    }
}

示例:

[Fact]
public void Test()
{
    var fixture = new Fixture();
    fixture.ResidueCollectors.Add(
        new MockRelay(
            new DbSetTypeSpecification()));

    Assert.DoesNotThrow(() => 
        fixture.Create<PriceService>());
}

现在,AutoFixture可以提供自动生成的PriceService值.

Now AutoFixture can provide auto-generated PriceService values.

请注意,MyContext类也是公共的,并且AFAICT也具有公共的构造函数.这意味着默认情况下,AutoFixture不会为MyContext类提供自动模拟的实例.

Please note that the MyContext class is also public and, AFAICT, it has a public constructor too. This means that AutoFixture will not supply an auto-mocked instance for MyContext class by default.

(如果您能提供自己的方案,我也许可以提供进一步的帮助.)

(If you can provide your scenario I might be able to help further.)

这篇关于如何使用Moq&amp;来模拟实体框架6自动固定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆