模拟 TDD 存储库的 DbContext

本文关键字:DbContext 存储 TDD 模拟 | 更新日期: 2023-09-27 18:31:59

试图模拟我的EF上下文,它与我的存储库耦合。我使用 Moq,尝试设置一个模拟上下文并通过构造函数将其传递到存储库中。

之后,我调用 Add 方法,简单地添加一个新对象,之后我尝试通过检查我传入的上下文是否更改了状态来断言......

我得到的错误是一个空引用异常,我想这是因为我的嘲笑不正确。

这是代码:

使用不工作模拟进行测试

[TestClass]
public class GameRepositoryTests
{
    [TestMethod]
    public void PlayerThatWonMustBeAddedToTopList()
    {
        // Arrange
        var expected = "Player added successfully";
        var dbContextMock = new Mock<Context>();
        // Need to setup the Context??
        IRepository gameRepository = new GameRepository(dbContextMock.Object);
        var user = "MyName";
        // Act
        gameRepository.Add(user);
        // Assert
        dbContextMock.VerifySet(o => o.Entry(new ScoreBoard()).State = EntityState.Added);
    }
}
public class ScoreBoard
{
}

存储 库

public class GameRepository : IRepository
{
    private readonly Context _context;
    public GameRepository()
        : this(new Context())
    {
        // Blank!
    }
    // Passing in the Mock here...
    public GameRepository(Context context)
    {
        this._context = context;
    }
    // Method under test...
    public void Add<T>(T entity) where T : class
    {
        _context.Set<T>().Add(entity);
    }
}

上下文

public class Context : DbContext
{
    public Context()
        : base("name=DefaultConnection")
    {
    }
}

模拟 TDD 存储库的 DbContext

你需要模拟Set<T>()调用。

这样的事情应该可以解决。

// Arrange
var context = new Mock<Context>();
var set = new Mock<DbSet<User>>();
context.Setup(c => c.Set<User>()).Returns(set.Object);
// Act
// Assert
set.Verify(s => s.Add(It.IsAny<User>()), Times.Once());

除了在底层DbSet上调用Add()之外,您实际上不需要验证任何内容。无需验证实体状态是否已被修改。如果验证是否调用了Add(),则应该足够了,因为可以安全地假定 EF 工作正常。

此示例仅适用于 User 对象的存储库。您必须为要以这种方式测试的每个存储库设置不同的模拟。如果需要,您可以编写一个更通用的版本。