这篇文章是“ 传统代码到可测试代码 ”系列的一部分。 在本系列中,我们将讨论在为遗留代码编写测试之前进行重构的步骤,以及它们如何使我们的生活更轻松。 它延续了关于访问器的最后一个帖子 。
我们讨论了“ setter”访问器作为注入价值的手段。 硬币的另一面是当我们想知道物体内部发生了什么事情时。 例如,如果内部状态已更改,或者调用了非公共方法。
实际上,这就像“如果树木掉下树林”这样的问题:为什么我们要关心内部状态是否发生变化?
在遗留代码中,在许多情况下,类会变大并且会做很多事情。 如果我们将职责分开,则可以在另一个类中声明结果。 god,与上帝的物体一起,事情有点混乱。 发生这种情况时,我们的接受标准可能会移入内部:我们可以检查内部状态或内部方法调用的影响。
要检查内部状态,我们可以添加一个“ getter”方法。 添加“ getter”功能很容易,如果它没有逻辑(也不应该),则可以公开信息而不会造成任何伤害。 如果重构工具要求您添加“设置者”,则可以将其设置为私有,因此没有人可以使用它。
角色反转
以一种有趣的方式,“ getter”方法可以颠倒角色:我们可以使用“ getter”方法通过模拟值来注入值。
因此,在我们的getAccount示例中:
protected Bank getBank() {
return new Bank();
}public void getAccount() {
Bank tempBank = getBank();
...
通过模拟getBank方法,我们可以返回一个模拟银行 (根据我们选择的工具):
when(testedObject.getBank()).thenReturn(mockBank);
另一方面,我们可以验证对“设置者”的调用,而不需要公开值。 因此,如果我们的Account对象具有称为balance的内部状态,而不是在测试操作后公开它并对其进行检查,则可以添加一个“ setter”方法,然后查看它是否被调用。
verify(account).setBalance(3);
与注入相反,当我们进行探测时,我们不想在堆栈上暴露对象。 它在一个操作的中间,因此并不有趣(并且很难检查)。 如果有实际情况,我们可以使用“ setter”方法验证选项。
在此示例中, addMoney函数在将值设置回currentBalance之前计算interimBalance 。
public void addMoney(int amount) {
int interimBalance = currentBalance;
interimBalance += amount;
currentBalance = interimBalance;
}
如果要在计算之前检查“ currentBalance”,可以将方法修改为:
public void addMoney(int amount) {
int interimBalance = setInterim(currentBalance);
interimBalance += amount;
currentBalance = interimBalance;
}protected void setInterim (int balance){
return balance;
}
然后,在我们的测试中,我们可以使用验证作为前提:
verify(account).setInterim(100);
添加访问器是解决我们在考虑测试之前就已经创建的问题的解决方案:设计不够模块化,肩负着许多责任。 它在其中保存信息,而测试(以及将来的客户端)无法访问它。 如果我们第一次把它写成“正确的”,那么神的类很可能被写成一组类。 通过适当的测试,我们希望实现模块化设计。
测试使我们可以安全地更改代码。 自动重构工具也是如此。 我们甚至可以在使用提取方法重构模式进行测试之前就开始分离。
接下来我们将讨论它。
翻译自: https://www.javacodegeeks.com/2014/10/legacy-code-to-testable-code-4-more-accessors.html