2013-10-11 33 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))));