【问题标题】:Mock DbContext.set<T>.Add() EF6模拟 DbContext.set<T>.Add() EF6
【发布时间】:2014-06-24 19:56:29
【问题描述】:

我有以下类(其中 PilsnerContext 是 DbContext 类):

public abstract class ServiceBase<T> : IService<T> where T: class, IEntity
{
    protected readonly PilsnerContext Context;

    protected ServiceBase(PilsnerContext context)
    {
        Context = context;
    }

    public virtual T Add(T entity)
    {
        var newEntity = Context.Set<T>().Add(entity);
        Context.SaveChanges();
        return newEntity;
    }
}

public class ProspectsService : ServiceBase<Prospect>
{
    public ProspectsService(PilsnerContext context) : base(context){}

}

我正在尝试对模拟上下文的 Add 方法进行单元测试,例如:

[TestClass]
public class ProspectTest
{
    [TestMethod]
    public void AddProspect()
    {
        var mockProspect = new Mock<DbSet<Prospect>>();
        var mockContext = new Mock<PilsnerContext>();

        mockContext.Setup(m => m.Prospects).Returns(mockProspect.Object);

        var prospectService = new ProspectsService(mockContext.Object);

        var newProspect = new Prospect()
        {
            CreatedOn = DateTimeOffset.Now,
            Browser = "IE",
            Number = "1234567890",
            Visits = 0,
            LastVisitedOn = DateTimeOffset.Now
        };

        prospectService.Add(newProspect);

        mockProspect.Verify(m=>m.Add(It.IsAny<Prospect>()), Times.Once);
        mockContext.Verify(m=>m.SaveChanges(), Times.Once);
    }
}

但是断言:

mockProspect.Verify(m=>m.Add(It.IsAny<Prospect>()), Times.Once);

失败了,我认为是因为我在 Add 方法中使用 Context.set().Add() 而不是 Context.Prospects.Add() 但是如何通过此测试的正确方法?

例外是:

Expected invocation on the mock once, but was 0 times: m => m.Add(It.IsAny<Prospect>()) No setups configured. No invocations performed.

提前致谢。

【问题讨论】:

标签: c# .net entity-framework unit-testing moq


【解决方案1】:

看来您只是缺少返回DbSet 的设置:

mockContext.Setup(m => m.Set<Prospect>()).Returns(mockProspect.Object);

【讨论】:

  • DbSet.Set() 是一个非虚方法。
  • The docs 说是,除非我看错了方法。我不是 EF 用户,所以我可能完全错了。
  • 显然该方法是在this commit 中虚拟化的,它在 EF 6.1.0 及更高版本中。只要确保我没有疯!
  • msdn 上的大多数示例是使用服务并直接使用上下文;没有这一行,通用存储库无法测试!谢谢...
  • 在我看来这应该是问题的答案
【解决方案2】:

我尝试了您的解决方案 Patrick Quirk,但我收到一条错误消息,告诉我 DbContext.Set 不是虚拟的。

我在这里找到了解决方案:

How to mock Entity Framework 6 Async methods?

创建一个类似 DbContext 的接口

    public interface IPilsnerContext
   {
       DbSet<T> Set<T>() where T : class;
   }

这样我就可以嘲笑它了。

谢谢!

这是我的第一个问题顺便说一句,我不确定我是否可以将此问题标记为重复或其他问题。

【讨论】:

  • 这个问题非常接近,我会将您的问题标记为可能重复的问题。你的问题是你链接到的问题的一个子集,所以我认为这是合格的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 2017-09-11
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2017-08-24
相关资源
最近更新 更多