如何使用模拟存储库测试CRUD?

时间:2019-11-09 10:50:06

标签: c# repository-pattern

我知道有很多这样的问题/文章,我已经读过很多次了,但是我仍然很困惑。

我有一个非常简单的代码。数据库=>实体框架=>存储库=>逻辑=>显示并立即测试。我的问题是我找不到如何测试CRUD操作的帮助。我只有以下说明:“使用模拟存储库进行测试”。因此以下内容毫无疑问。

    [Test]
    public void TestThatReadCrewWorks()
    {
        CrewLogic logic = new CrewLogic();
        var result = logic.LReadCrew(102);
        Assert.That(result.Name, Is.EqualTo("Test Joe"));
    }

我如何使用我的存储库(使用dbcontext)进行独立测试,而不给测试dll提供连接字符串?我尝试过...

    [Test]
    public void TestThatCreatingCrewWorks2()
    {
        DbContext ctx;
        CrewRepository newc = new CrewRepository(ctx);
    }

...从这里开始完全黑暗。 dbcontext应该在这里什么?

任何帮助,甚至链接都非常适用。谢谢。

编辑:澄清

public abstract class Repository<T> : IRepository<T>
    where T : class
{
    protected DbContext ctx;

    public Repository(DbContext ctx)
    {
        this.ctx = ctx;
    }

    public T Read(int id)
    {
        return this.ctx.Set<T>().Find(id);
    }
    //...and other crud operations
 }

我有这种语法。如何编写测试,该测试取决于此常规DBcontext而不是我的实际数据库。我应该以某种方式创建假课程吗?

1 个答案:

答案 0 :(得分:1)

您的存储库只是包装DbContextDbContext本身已经在发布之前经过Microsoft的测试。无需测试DbContext是否达到了设计的目的。

要测试存储库是否按预期使用了上下文,那么您需要对实际上下文进行集成测试。模拟return this.ctx.Set<T>().Find(id);或使用内存DbContext。无论哪种方式,您的测试都会给人一种错误的安全感,因为您基本上是在测试已由其开发人员测试过的包装代码。

例如,您在基础存储库中的[Test] public void CrewWorks_Should_Find_By_Id() { //Arrange int expectedId = 102; string expectedName = "Test Joe"; Crew expected = new Crew { Id = expectedId, Name = "Test Joe" }; Mock<DbContext> ctxMock = new Mock<DbContext>(); ctxMock .Setup(_ => _.Set<Crew>().Find(expcetedId)) .Returns(expected); DbContext ctx = ctxMock.Object; CrewRepository subject = new CrewRepository(ctx); //Act Crew actual = subject.Read(expectedId); //Assert Assert.That(actual, Is.EqualTo(expected)); } 。该行中的所有内容都与DbContext相关,值得您去做的事情不值得您测试。

例如,看一下对同一存储库方法的以下测试

[Test]
public void TestThatReadCrewWorks() {
    int expectedId = 102;
    string expectedName = "Test Joe";
    Crew expected = new Crew {
        Id = expectedId,
        Name = "Test Joe"
    };
    //Assuming abstraction of specific repository 
    //  interface ICrewPrepsitory: IRepository<Crew> { }
    ICrewPrepsitory repository = Mock.Of<ICrewPrepsitory>(_ =>
        _.Read(expectedId) == expected
    );

    CrewLogic logic = new CrewLogic(repository); //assuming injection

    //Act
    var actual = logic.LReadCrew(expectedId);

    //Assert
    Assert.That(actual.Name, Is.EqualTo(expectedName));
    //...other assertions
}

以上测试验证了与包装的{{1}}相关的调用的预期行为,并且在安全性方面并没有提供太多帮助,因为它基本上是在测试包装的代码是否被调用。

理想情况下,应该对存储库进行模拟并用于更高级别的逻辑测试

{{1}}