为TDD存储库模拟DbContext

时间:2014-11-25 15:48:40

标签: c# asp.net-mvc unit-testing tdd

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

之后我调用Add方法,只需添加一个新对象,然后通过检查传入的上下文是否已更改状态来尝试Assert ...

错误我得到的是一个NullReference异常,我猜它是因为我的嘲弄不正确..

这是代码:

测试没有工作模拟

[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")
    {

    }
}

1 个答案:

答案 0 :(得分:1)

您需要模拟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());

除了在基础Add()上调用DbSet之外,您确实无需进行任何验证。对实体状态被修改这一事实进行验证是不必要的。如果您确认调用了Add(),那就足够了,因为您可以安全地假设EF正常工作。

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