使用伪造的DbContext和Autofixture以及Moq进行测试

时间:2013-05-22 16:16:43

标签: entity-framework asp.net-mvc-4 nunit moq autofixture

所以请遵循这个例子

example以及如何使用假的DBContex来测试我的测试只使用这项工作

[Test]
public void CiudadIndex()
{
    var ciudades = new FakeDbSet<Ciudad>
    {
        new Ciudad {CiudadId = 1, EmpresaId =1, Descripcion ="Santa Cruz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
        new Ciudad {CiudadId = 2, EmpresaId =1, Descripcion ="La Paz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
        new Ciudad {CiudadId = 3, EmpresaId =1, Descripcion ="Cochabamba", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1}
    };

    //// Create mock unit of work
    var mockData = new Mock<IContext>();
    mockData.Setup(m => m.Ciudades).Returns(ciudades);

    // Setup controller
    var homeController = new CiudadController(mockData.Object);

    // Invoke
    var viewResult = homeController.Index();
    var ciudades_de_la_vista = (IEnumerable<Ciudad>)viewResult.Model;

    // Assert..
}

我现在尝试使用Autofixture-Moq

创造“ciudades”,但我不能。我试试这个

var fixture = new Fixture();
var ciudades = fixture.Build<FakeDbSet<Ciudad>>().CreateMany<FakeDbSet<Ciudad>>();
var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);

我收到此错误

  

不能将System.Collections.Generic.IEnumerable(FakeDbSet(Ciudad))转换为System.Data.Entity.IDbSet(Ciudad)

不能放“&lt;&gt;”所以我用错误信息中的“()”替换

IContext和FakeDbSet的实现

public interface IContext
{
    IDbSet<Ciudad> Ciudades { get; }
}
public class FakeDbSet<T> : IDbSet<T> where T : class

如何才能使其发挥作用?

3 个答案:

答案 0 :(得分:3)

一个小问题......在像:

这样的东西
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();

第二种类型的arg是不必要的,应该是:

var ciudades_fixture = fixture.Build<Ciudad>().CreateMany();

我真的明白为什么你需要一个FakeDbSet而且这篇文章有点TL; DR ...一般来说,我试图避免伪造和混淆ORM位,而是处理返回POCO的接口到最大值可能的程度。

除此之外......初始化列表的正常语法起作用的原因是DBFixture中存在Add(和IEnumerable)。 AutoFixture没有直接针对该模式的故事(毕竟它是编译器语法糖,并不特别适合反射或符合任何其他约定)但只要有{AddManyTo就可以使用ICollection 1}}在游戏中。幸运的是,在文章中FakeDbSet的内容中,以下内容为我们提供了一个: -

public ObservableCollection<T> Local
{
    get { return _data; }
}

由于ObservableCollection<T>来自ICollection<T>,您应该能够:

var ciudades = new FakeDbSet<Cuidad>();
fixture.AddManyTo(ciudades.Local);

var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);

可以连接自定义以使其更漂亮,但至少您有办法管理它。另一种选择是让某些东西实现ICollection(或者使用IEnumerable<T>添加一个带有setter 的prop 并让AF生成父对象,从而填充所述集合。


长期取代的旁注:在您的初步问题中,您实际上有:

fixture.Build<FakeDbSet<Ciudad>>().CreateMany()

问题变得更加清晰了 - 你要求AF生成许多 FakeDbSet<Ciudad>,这不是你想要的。

答案 1 :(得分:1)

我有一段时间没有使用过AutoFixture,但不应该是:

var ciudades = new FakeDbSet<Ciudad>();
fixture.AddManyTo(ciudades);

答案 2 :(得分:0)

目前我这样做,我会继续阅读有关如何使用automoq,因为我是新手

var fixture = new Fixture();
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();
var ciudades = new FakeDbSet<Ciudad>();
foreach (var item in ciudades_fixture)
{
    ciudades.Add(item);
}
var mockData = new Mock<IContext>(); 
fixture.Create<Mock<IContext>>();
mockData.Setup(r => r.Ciudades).Returns(ciudades);