2013-10-11 32 views
6

我使用AutoMoq但我有点困惑如何写,因为我的第一个单元测试实体框架的(使用EF6和代码第一)dbContext如何实体模型实体框架6随着起订量:Autofixture

// 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>(); 

当我运行单元测试崩溃

 
    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更mockable。

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

让DbSet更mockable

  • 这意味着将受保护的构造和制作方法虚拟
  • 注意,从DbSet派生的类型,使用受保护的构造函数创建一个对象不受任何环境的约束,方法将是无效的。从创建测试双打的角度来看,这非常像IDbSet。
  • 如果我们采用这个选项,我们可能会过时IDbSet
  • 值得注意的是,没有发现任何情况下,这在功能上与使用IDbSet进行测试双打不同。但是,社区中强烈的感觉是接口更受欢迎。

任何人都知道如何模拟它?

编辑2

我发现this article但它总是崩溃

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 = a621a9e7e5c32e69'试图隐式地覆盖一个弱类型参数约束的方法。

+1

相关:HTTP://计算器。 com/questions/16696777/testing-with-a-fake-dbcontext-and-autofixture-and-moq and http://stackoverflow.com/questions/14391146/using-autofixture-in-my-data-integration-tests- to-create-proxies和https://autofixture.codeplex.com/discussions/262557问题:你是否分离出EF6实际上表现得与5不同,还是只是试图完成? –

+0

您提供的最后一个示例是没有AutoFixture的示例,它适用于我的机器。我已经复制了你的PriceService,MyContext类和Test_Price_Object_Setup_Properly方法。我实现了我自己的Price类,因为你没有提供它,它没有任何例外运行。我正在使用Entity Framework 6.0 RC 1和Visual Studio 2013 RC。 –

+0

@RubenBartelink那么我的问题开始出来如何模拟Datacontext,然后我发现EF可以在dbset上做模拟,并且不需要包装。我在教程中遇到了很多问题。我现在知道这是自动混合问题,它安装了moq的3.0版本,但本教程需要4.0才能工作。我不确定现在是否可以使用自动混合。 – chobo2

回答

4

您需要提供一个specification这表明DbSet<T>类应该被嘲笑(虽然它不是一个抽象类或接口)。

原因是因为DbSet<T>类是公共的,但它具有保护构造函数。

规格

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值。


请注意MyContext类也是公众和,AFAICT,它有一个公共的构造函数了。这意味着默认情况下,AutoFixture不会为MyContext类提供自动模拟实例。

(如果你能提供你的情况我可能能够进一步帮助)

+0

您是否尝试过使用EF 6?我发现为什么没有为我工作的原因是AutoFixture安装了moq 3,我需要moq 4才能使用该教程,我试图保留moq 4和autofixture,但后来我从来没有可能导入夹具“使用” – chobo2

+0

嗯,我只是看着Autofixture从来没有真正使用它之前我想设置我的测试,所以我不必手动创建所有的模拟(moq)和虚拟数据。这就是我想要做的,当我在模拟中需要某些数据是某个值时(比如PriceObject的价格必须是5),我也有点不清楚。 – chobo2

+0

@ chobo2关于Moq请阅读我的答案[这里](https://autofixture.codeplex.com /工作项/ 4260)。 –

1

有一个NuGet包称为AutoFixture.AutoEF这可以解决您的问题

fixture.Customize(new EntityCustomization(new DbContextEntityTypesProvider(typeof(MyContext))));