我已经开始在我的项目中遵循 TDD。但自从我开始,即使读了一些文章,我也很困惑,因为发展速度变慢了。每当我重构代码时,我都需要更改之前编写的现有测试用例,否则它们将开始失败。
下面是我最近重构的一个类的例子:
public class SalaryManager
{
public string CalculateSalaryAndSendMessage(int daysWorked, int monthlySalary)
{
int salary = 0, tempSalary = 0;
if (daysWorked < 15)
{
tempSalary = (monthlySalary / 30) * daysWorked;
salary = tempSalary - 0.1 * tempSalary;
}
else
{
tempSalary = (monthlySalary / 30) * daysWorked;
salary = tempSalary + 0.1 * tempSalary;
}
string message = string.Empty;
if (salary < (monthlySalary / 30))
{
message = "Salary cannot be generated. It should be greater than 1 day salary.";
}
else
{
message = "Salary generated as per the policy.";
}
return message;
}
}
但现在我用一种方法做很多事情,所以为了遵循单一职责原则(SRP),我将其重构为如下所示:
public class SalaryManager
{
private readonly ISalaryCalculator _salaryCalculator;
private readonly SalaryMessageFormatter _messageFormatter;
public SalaryManager(ISalaryCalculator salaryCalculator, ISalaryMessageFormatter _messageFormatter){
_salaryCalculator = salaryCalculator;
_messageFormatter = messageFormatter;
}
public string CalculateSalaryAndSendMessage(int daysWorked, int monthlySalary)
{
int salary = _salaryCalculator.CalculateSalary(daysWorked, monthlySalary);
string message = _messageFormatter.FormatSalaryCalculationMessage(salary);
return message;
}
}
public class SalaryCalculator
{
public int CalculateSalary(int daysWorked, int monthlySalary)
{
int salary = 0, tempSalary = 0;
if (daysWorked < 15)
{
tempSalary = (monthlySalary / 30) * daysWorked;
salary = tempSalary - 0.1 * tempSalary;
}
else
{
tempSalary = (monthlySalary / 30) * daysWorked;
salary = tempSalary + 0.1 * tempSalary;
}
return salary;
}
}
public class SalaryMessageFormatter
{
public string FormatSalaryCalculationMessage(int salary)
{
string message = string.Empty;
if (salary < (monthlySalary / 30))
{
message = "Salary cannot be generated. It should be greater than 1 day salary.";
}
else
{
message = "Salary generated as per the policy.";
}
return message;
}
}
这可能不是最好的例子。但要点是,一旦我进行了重构,我为SalaryManager
开始失败,我不得不使用模拟来修复它们。
这种情况在读取时间场景中经常发生,并且开发时间也随之增加。我不确定我是否以正确的方式进行 TDD。请帮助我理解。
每当我重构代码时,我都需要更改之前编写的现有测试用例,因为它们会开始失败。
这肯定表明出现了问题。重构的流行定义是这样的this https://refactoring.com/
重构是一种严格的技术,用于重组现有代码体,改变其内部结构而不改变其外部行为。
进行单元测试的部分目的是单元测试正在评估实现的外部行为。失败的单元测试表明实现更改以某种方式改变了外部可观察的行为。
在这种特殊情况下,您似乎更改了 API - 具体来说,您删除了默认构造函数,该构造函数是用于创建实例的 API 的一部分SalaryManager
;这不是“重构”,而是向后的破坏性改变。
在重构时引入新的协作者并没有什么问题,但您应该以不破坏当前 API 契约的方式这样做。
public class SalaryManager
{
public SalaryManager(ISalaryCalculator salaryCalculator, ISalaryMessageFormatter _messageFormatter){
_salaryCalculator = salaryCalculator;
_messageFormatter = messageFormatter;
}
public SalaryManager() {
this(new SalaryCalculator(), new SalaryMessageFormatter())
}
where SalaryCalculator
and SalaryMessageFormatter
应该是产生与您最初相同的可观察行为的实现。
当然,有时我们需要引入向后的突破性改变。然而,“重构”并不是适合这种情况的工具。在许多情况下,您可以分几个阶段实现您想要的结果:首先使用新测试扩展您的 API(重构以删除与现有实现的重复),然后删除评估旧 API 的测试,最后删除旧 API。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)