【发布时间】:2020-02-07 01:50:31
【问题描述】:
我们有这样的业务流程
- 从数据库中获取列表数据
- 对于列表中的每个项目
- 将项目转换为 JSON
- 发送数据给第三方获取结果
- 将结果保存到数据库
Send data 会因第三方而异,一种需要使用 HTTP,一种需要使用 FTP 或 gRPC 调用。我使用接口将发送数据抽象给第三方,并让 API(外部层)决定它要使用哪种方法。
架构遵循 Clean Architect。我们在中间有实体、业务/核心以及 API 和基础架构的包装器。
代码示例
In Business/Core project
// Abstract class
var items = await GetItemsAsync(args); // abstract method
foreach (var item in items)
{
var json = await ConvertItemToJsonAsync(item); // abstract method
var resultInString = await SendAsync(json); // abstract method
await SaveResultAsync(item, resultInString); // abstract method
}
// Now for child classes, they will implement those abstract methods.
// In this case, it will be
override Task<string> SendAsync(string json)
{
return _thirdparty.SendDataAsync(json);
}
interface IThirdParty
{
Task<string> SendDataAsync(string json);
}
这意味着子类将接受一个名为 _thirdparty 的接口来解耦发送数据到第三方。在 API 层,很容易创建一些第三方,例如通过 HTTP、FPT 或 gRPC 发送,并注册 DI 或更好的工厂使用。
我关心单元测试,当您编写单元测试时,您需要一个上下文,有了上下文,您就知道编写测试用例/脚本的单元是什么。 例如,如果我们创建一辆汽车,上下文是一辆基本上可以驾驶的汽车。我们应该关心使用什么样的车轮螺丝吗?它来自供应商的组装护理部件。如果我们测试组装的每个部分,我们需要关心螺丝。那是一个上下文。如果按照上面的方法,我可以很容易地为每个抽象方法和整个流程编写一个单元测试,我可以为第三方创建一个模拟接口。
但是Business/Core有一个问题,因为这个业务的重点是调用第三方,也就是一个context,其余的方法都是和db打交道的,我们不用测试。
为了让我可以在Business/Core中测试流,我需要将第三方的具体类从API移动到Business/Core中,然后我可以将它作为一个单元进行测试。通过这样做,Business/Core 现在需要使用称为 HttpClient、gRPC 类的东西来与第三方合作。
我的问题是,如果网络是其业务,企业是否应该关心网络?或者我们有什么更好的方法来解决它?
【问题讨论】:
-
如果我没有 100% 误解:为什么不在业务/核心代码中为抽象层定义接口,然后在其他地方实现抽象层?那么业务/核心层就不需要关心或了解HttpClient、gRPC等。
-
这就是我正在做的,它提出了我的问题
-
那为什么业务/核心层需要知道或关心HttpClient、gRPC等呢?
-
“这是一个上下文”——这是什么意思?
-
我认为你看错了。我并不是说不要测试联系第三方 API 的实际代码。如果需要,您可以为此编写集成测试。我是说你在业务层需要测试的只是它在接口上正确调用了正确的方法。然后你有一个单独的测试来确保
IThirdParty的真正实现可以正常工作。
标签: c# unit-testing clean-architecture