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

问题描述 投票:1回答:1

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

我有一个非常简单的代码。数据库=>实体框架=>存储库=>逻辑=>显示并立即测试。我的问题是我找不到如何测试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而不是我的实际数据库。我应该以某种方式创建假课程吗?

c# repository-pattern
1个回答
1
投票

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

要测试存储库是否按预期使用了上下文,那么您需要对实际上下文进行集成测试。模拟DbContext或使用内存中的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
}
© www.soinside.com 2019 - 2024. All rights reserved.