下面给出的是我的产品代码本质和简化表示。这就像一个完成工作流程的算法。每个步骤(私有方法)都会导致数据库中的记录发生更改。甚至外部工具调用也会导致通过另一种回调反馈机制更新数据库。
void IWorkFlow.PerformBusinessWorkflowX(Input input)
{
PreparePreRequisiteData();
DoTask_A();
TriggerExternalToolTo_DoTask_B(); /* external tool invocation */
}
我的一位同事想为此编写一个集成测试用例,但不想包含外部工具调用。如果 BusinessWorkFlow 逻辑处于集成级别但不包括外部工具,他的目标是测试其余部分。不是使用模拟的单元测试,而是集成测试,他在其中验证数据库前后测试的状态。为了达到目的,他修改了这样的代码。
void IWorkFlow.PerformBusinessWorkflowX(Input input, bool isTriggerExternalTool)
{
PreparePreRequisiteData();
DoTask_A();
if(isTriggerExternalTool)
{
TriggerExternalToolTo_DoTask_B(); /* external tool invocation */
}
}
但是,我对这种重构风格不满意。由于外部工具的调用是业务工作流程中不可分割/不可分割的一部分,因此我宁愿不要将产品代码修改为具有指示工具调用是可选的布尔标志。
我认为更好的解决方案(但丑陋(?)因为它的性质)是坚持使用原始方法而不需要传入布尔标志依赖项。相反,决定调用该工具以支持嵌入在TriggerExternalToolTo_DoTask_B() 方法。或者甚至调用它 TryTriggerExternalToolTo_DoTask_B()。
就像是,
private void TryTriggerExternalToolTo_DoTask_B()
{
//will be false for integration tests. Any other value then invoke.
if(ConfigurationManager.AppSettings["InvokeTool"] != "false")
{
}
}
我也不赞成将 IWorkFlow.PerformBusinessWorkflowX(Input input) 方法分解为两部分(一部分执行前两个步骤,第二部分仅执行通过不同接口方法公开的工具调用),只是为了在产品代码方面具有灵活性并支持测试代码。也因为所有步骤都属于单个工作流程(算法)。
问题
1)我是否错误地说在产品代码中引入布尔标志只是为了支持测试可能不是最佳实践?(有些人告诉我,这就是可测试性设计。我希望这不是可测试性设计的真正含义)
2) 将调用逻辑推入 TryTriggerExternalToolTo_DoTask_B() 并依靠 appsetting 来救援的看似丑陋的解决方案是更好的解决方案吗?
3)看到我不想为了灵活性而分解方法(扩展接口),有没有更好的解决上述问题的方法?
PS - 如果我不了解,请纠正我并提供开放的技术建议。