用模拟上下文提供我的模拟模型

时间:2016-11-18 05:54:26

标签: c# wpf entity-framework unit-testing moq

用几句话说。 Wpf应用程序,如果使用。我需要使用mock和unity来测试模型行为。在我看来,团结和模拟是清楚的。

问题如下:
模型没有通过它构造函数获取上下文。它在执行如下方法时使用上下文:

public Toys[] Get()
{
    using (Context context = new Context())
    {
        return context.Toys.ToArray();
    }
}

这是我尝试测试的方式:

[TestClass]
public class TestToyModel
{
    [TestMethod]
    public void TestToyCreate()
    {
        List<Toy> toys = new List<Toy>();
        toys.Add(new Toy{ Id = "1234", Name = "Toy1" });

        DbSet<Toy> dbToys = GetQueryableMockDbSet(toys);

        Mock<ToyModel> model = new Mock<ToyModel>();
        Mock<Context> context = new Mock<Context>();
        context.Setup(x => x.Toys).Returns(dbToys);
        //it' s all for now
    }

    private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
    {
        var queryable = sourceList.AsQueryable();

        var dbSet = new Mock<DbSet<T>>();
        dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
        dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
        dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
        dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));

        return dbSet.Object;
    }
}

如何使用模拟上下文提供我的模拟模型?

1 个答案:

答案 0 :(得分:1)

正在手动创建上下文,因此类与上下文紧密耦合,这使得单独进行单元测试变得困难。

上下文是一种依赖。将其抽象出来,以便将其嘲笑并注入被测试对象。<​​/ p>

notifyItemChanged(itemPosition);

假设受测试系统

public interface IContext : IDisposable {

    public DbSet<Toy> Toys { get; }

    //...other properties and methods
}

public class Context : DbContext, IContext {

    public Context() { ... }

    public DbSet<Toy> Toys { get; set; }

    //...other properties and methods
}

该类不再负责创建依赖项。现在,该职责被传递/委托给另一个班级。另请注意,您的类应该依赖于抽象而不是结构。这样可以在交换实现时提供更大的灵活性。就像嘲笑单元测试一样。

现在可以模拟上下文并将其注入到依赖类中。这是一个简单的例子,基于你到目前为止所做的事情。

public class ToyModel {
    private readonly IContext context;

    public MyClass(IContext context) {
        this.context = context;
    }

    public Toys[] Get() {
        return context.Toys.ToArray();
    }

    public void Create(Toy toy) {
        context.Toys.Add(toy);
        context.SaveChanges();
    }
}

如果[TestClass] public class TestToyModel { [TestMethod] public void TestToyCreate() { //Arrange var toys = new List<Toy>(); toys.Add(new Toy { Id = "1234", Name = "Toy1" }); var dbToys = GetQueryableMockDbSet(toys); //DbSet<Toy> var contextMock = new Mock<IContext>(); contextMock.Setup(x => x.Toys).Returns(dbToys); var sut = new ToyModel(contextMock.Object); //Act sut.Create(new Toy { Id = "5678", Name = "Toy2" }); //Assert var expected = 2; var actual = toys.Count; Assert.AreEqual(expected, actual); } //...other code removed for brevity } 是被测系统,则无需嘲笑它。创建一个实例并传递模拟的依赖项以满足测试。