【发布时间】:2018-11-27 23:08:44
【问题描述】:
我已简化示例中的代码以缩短问题,但基本上我正在努力设计更多可测试的代码并将它们彼此隔离。
通过下面列出的两种方法,我已经准确地概述了我需要做的测试。
- 验证是否使用了正确的 URL
- 验证是否使用了适当的标头,例如请求是 JSON 格式。
- 验证是否使用了 POST 请求(我有一个 HttpMessageHandler 并使用委托来拦截和模拟 Internet 作为实际代码中的依赖项)
- 验证序列化的 JSON 值没有任何未填写的额外属性。
代码示例如下:
class RESTAPI
{
private IHttpService _webService;
public void ChangeAssignedAgent(ITicket ticket, string agentName)
{
string agentID = GetAgentIDFromName(agentName);
_webService.PostRequest($"https://localhost/{agentID}", new StringContent(JsonConvert.SerializeObject(ticket), Encoding.UTF8,"application/json"));
}
private string GetAgentIDFromName(string agentName)
{
return JsonConvert.DeserializeObject<JObject>(_webService.GetStringContent($"https://localhost/{agentName}"))["sys_id"].Value<string>();
}
}
理论上,这些测试应该彼此完全隔离。 但不是因为在每次测试中,我都必须设置和配置 GetAgentFromName(),即使它不相关。
这是我解决此问题的想法,但我不确定最好的解决方案是使某些东西更加面向 SRP 和可测试。
使用装饰器或适配器将 agentName 简单地转换为 agentID,然后将此信息传递给基类以发布请求。
将私有方法更改为受保护的内部方法,让一个模拟框架替换 GetAgentIDFromName() 方法的实现,并简单地调用任何未被模拟的方法的基本实现。
更改 ChangeAssignedAgent() 方法的方法签名,改为引用获取 agentID 而不是名称,公开 GetAgentIDFromName() 并期望您的类的使用者使用它来使用 ChangeAssignedAgent () 方法。
第一个选项可能是解决这种情况的最佳方法,但有些事情告诉我这可能不是正确的解决方案,因为从技术上讲,基类具有误导性......它需要一个 agentName......而不是一个 ID。
第二个选项对我来说似乎更像是一种 hack 和代码味道,它正在有效地测试一种私有方法...我不确定...欢迎提出建议。
最后,最后一个选项...它与第二个选项相似,我觉得它可能是一种 hack/code 味道,但它对我来说最合乎逻辑。然而,这种设计感觉就像你永远不能拥有私有方法,而且它还可能增加你的类的复杂性。
我是不是想多了?我很想听听一些建议...
【问题讨论】:
标签: c# .net unit-testing oop single-responsibility-principle