如何测试依赖于数据库中的某些数据的方法,而无需为所有方法制作接口

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

我是编写测试的新手,并且遇到了以下问题。

我有一个带有公共方法的服务类,该方法根据数据库数据运行一些验证并返回一个布尔值,如下所示

public async Task<bool> IsSessionAllowed(SessionAlowedReq req)
{
        var data = await GetFromDB(/* some params*/);
        //process data... 
        return results;
}

GetFromDB 是一个私有方法,它进行 db 调用并返回一些 obj,然后我在 IsSessionAllowed 方法中处理该对象并检查一些业务规则并返回一个 bool。

现在我不想测试 GetFromDB 方法(我知道这将是更多的集成测试),我想做的是从 GetFromDB 方法给出不同的结果来测试 IsSessionAllowed 是否返回正确的结果。我发现做到这一点的一种方法是like this,这基本上使我将所有私有方法(在这个场景中)变成一个新接口,并让测试类提供它自己的实现。我发现对于那些永远不会单独使用的方法来说,拥有自己的接口只是为了测试目的,这根本不干净

那么还有其他方法可以做到这一点吗?

编辑: 这是我的私有方法的工作原理

 private async Task<dynamic?> GetFromDB(/* params */)
{
        //there are multiple DBs this returns the correct DbContext based on string
        DbContext db = _contextFactory.GetContext("some db");
        return await db.Set<TableName>()
            .Where(n =>
                n.ClientId == clientId &&
                n.StateId == stateId &&
                n.NoteDate.HasValue && n.NoteDate.Value.Date <= date.Date
            )
            .FirstOrDefaultAsync();
}
c# unit-testing asp.net-core xunit
1个回答
0
投票

如果您唯一关心的是测试特定的

IsSessionAllowed
方法,那么您可以使用此技术:

使

GetFromDB
受保护虚拟。 创建包含
GetFromDB
:

的类的可测试子类
public class TestableSession: SessionClass
{

    override protected Task<dynamic?> GetFromDB()
    {
        // return fake data
        return Task.FromResult<dynamic?>(null);
    }
 }

然后创建

TestableSession
作为 SUT 而不是真正的
SessionClass

[Fact]
public void Test1()
{
     var sut = new TestableSession();
     sut.IsSessionAllowed(req);
}

虽然您可能需要测试与 DbContext 交互的其他方法,但最好的选择是使用存储库模式或创建涉及真实数据库的集成测试,如 https://learn.microsoft.com/en- 中所述-我们/ef/核心/测试/

© www.soinside.com 2019 - 2024. All rights reserved.