我是编写测试的新手,并且遇到了以下问题。
我有一个带有公共方法的服务类,该方法根据数据库数据运行一些验证并返回一个布尔值,如下所示
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();
}
如果您唯一关心的是测试特定的
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/核心/测试/