【发布时间】:2013-10-11 22:27:51
【问题描述】:
我正在使用AutoMoq,但我有点困惑如何编写我的第一个单元测试,因为 Entity Framework(首先使用 EF6 和代码)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>();
当我运行单元测试时它崩溃了
在 Ploeh.AutoFixture.Kernel.TerminatingSpecimenBuilder.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.AutoPropertiesCommand`1.Execute(对象标本,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Collections.Generic.List`1..ctor(IEnumerable`1 集合) 在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.MethodInvoker.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.Postprocessor`1.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.c__DisplayClass6.b__1(ISpecimenBuilder b) 在 System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() 在 System.Linq.Enumerable.d__a5`1.MoveNext() 在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 源) 在 Ploeh.AutoFixture.Kernel.RecursionGuard.Create(对象请求,ISpecimenContext 上下文) 在 Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext 上下文,T 种子) 在 Ploeh.AutoFixture.SpecimenFactory.Create[T](ISpecimenContext 上下文) 在 PriceServiceTests.cs:line 26 中的 PriceServiceTests.Test_Price_Object_Setup()编辑
在 EF 6 中,它们似乎使 DbSet 更加可模拟。
使 DbSet 更可模拟
- 这意味着添加受保护的构造函数并使方法成为虚拟方法
- 请注意,从使用受保护构造函数的 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 'DbSet1Proxyb409fc6b430b4568aac048b60ea2f02e' 从程序集'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e66
【问题讨论】:
-
相关:stackoverflow.com/questions/16696777/… 和 stackoverflow.com/questions/14391146/… 和 autofixture.codeplex.com/discussions/262557 问题:您是否发现 EF6 实际上的行为与 5 不同,或者您只是想要完整?
-
您提供的最后一个示例,没有 AutoFixture 的示例适用于我的机器。我已经复制了您的 PriceService、MyContext 类和 Test_Price_Object_Setup_Properly 方法。我实现了我自己的 Price 类,因为你没有提供它并且它运行时没有任何异常。我正在使用实体框架 6.0 RC 1 和 Visual Studio 2013 RC。
-
@RubenBartelink 好吧,我的问题从如何模拟 Datacontext 开始,然后我发现 EF 可以在 dbset 上进行模拟并且不需要包装器。我在做教程时遇到了很大的问题。我现在知道问题出在 autofixture 上,它安装了 3.0 的最小起订量,但本教程需要 4.0 才能正常工作。因此,我不确定现在是否可以使用 autofixture。
-
@OlavNybø - 是的,它现在可以在我的机器上运行,因为您可能刚刚从它的 nuget 包中直接安装了 moq。我从 autofixture 得到它,它安装了版本 3,你需要 moq 版本 4 才能使那段代码工作。
-
@chobo 很高兴您现在可以使用它,并且 obv 不好,它花费了您时间到达那里。一般来说,AutoFixture 取决于 它 需要通过其测试的最早版本。如果您需要 Moq v4,因为您有一个具有奇怪依赖项的库。 AutoFixture.Xunit 是否需要 1.9.2,因为 1.8 不适用于 Tech Z ? IOW 我认为重要和有用的是 AF 不会强制依赖并非绝对必要的东西(例如 .NET 4 上的 3.0+ dep 最近让我刮了将近一天的牦牛毛 - 但我有机会投票决定 dep 是否还可以
标签: c# entity-framework nunit moq autofixture