![在 Java 中断言内部行为](http://img.jiangsulong.com/220505/1AF41361-1.jpg)
文章插图
到目前为止,一切都很好——如您所见,测试报告是绿色的 。
后来,我们决定重构 Leaderboard 类的内部结构,因此每当我们向其中添加新玩家时,它都会按降序对玩家列表进行排序:
package chaseandrace.player;import java.util.ArrayList;import java.util.Comparator;import java.util.List;public class Leaderboard {List<Player> players;public Leaderboard() {players = new ArrayList<>();}public void addPlayer(Player player) {this.players.add(player);this.players.sort(Comparator.comparing(Player::getScore, Comparator.reverseorder()));}public Player getBestPlayer() {if (players.isEmpty()) {return null;}return players.get(0);}}
package chaseandrace.player;import static org.junit.jupiter.api.Assertions.assertEquals;import org.junit.jupiter.api.Test;public class LeaderboardTest {@Testvoid getPlayerWithHighestScore() {var playerOne = new Player("I don't know what I'm doing here");var playerTwo = new Player("Chase me");var playerThree = new Player("Okie Dokie");playerOne.updateScore(50);playerTwo.updateScore(90);playerThree.updateScore(85);var board = new Leaderboard();board.addPlayer(playerOne);board.addPlayer(playerTwo);board.addPlayer(playerThree);var bestPlayer = board.getBestPlayer();assertEquals(playerTwo, bestPlayer);assertEquals(bestPlayer, board.players.get(1));}}
package chaseandrace.player;public class Player {private String name;private int score;public Player(String name) {this.name = name;}public int getScore() {return score;}public void updateScore(int points) {score += points;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return name;}}
![在 Java 中断言内部行为](http://img.jiangsulong.com/220505/1AF44019-2.jpg)
文章插图
让我们省略关于是否需要此更改的讨论——我想向您展示的是更改实现细节如何影响现有测试 。
如您所见,测试报告变为红色,但可观察到的行为保持不变——Leaderboard#getBestPlayer 函数仍然正常工作,它返回得分最高的玩家 。
如何解决这个问题? 如果在重构代码库的情况下,一次编写的测试不需要我们额外关注,那将是最好的 。为此,Leaderboard#players 列表应该无法从外部访问,因此使用 private 修饰符标记这个集合就足够了:
package chaseandrace.player;import java.util.ArrayList;import java.util.Comparator;import java.util.List;public class Leaderboard {private List<Player> players;public Leaderboard() {players = new ArrayList<>();}public void addPlayer(Player player) {this.players.add(player);this.players.sort(Comparator.comparing(Player::getScore, Comparator.reverseOrder()));}public Player getBestPlayer() {if (players.isEmpty()) {return null;}return players.get(0);}}
但是测试呢? 它现在有一个编译错误:![在 Java 中断言内部行为](http://img.jiangsulong.com/220505/1AF45B7-3.jpg)
文章插图
由于您的测试应该只验证可观察的行为,我们可以安全地从第 25 行删除断言,因为它检查实现细节,这使得该测试变得脆弱 。
结论
在项目中进行脆弱测试的后果可能非常严重 。例如,这样的测试可能会阻止开发人员重构代码,因为老实说——当你完成重构时,这导致了一堆失败的测试,这并不一定会让你心情愉快 。另一个可能的后果是,开发人员可以习惯于发出错误警报的测试,从而降低他们的整体警觉性,从而使错误潜入生产环境的机会增加 。
【在 Java 中断言内部行为】
推荐阅读
- go-micro集成链路跟踪的方法和中间件原理
- 如何恢复网站浏览记录?
- 计量检测中心校准证书上的CMA、CNAS、CAL有什么意义,区别在哪?
- 英式红茶泡几次,英式罐装红茶的泡法
- 明星|王牌:化妆师什么审美?给明星化妆,像是在脸上“刮大白”
- 饵料|《师傅请赐教》中年男人解压方式竟是夜钓?背后原因让人深思
- 中国最美乡村全集
- 中国最美丽的村庄是什么
- 冲红茶泡中间,润元昌红茶系列
- 骁龙8|中兴Axon 40 Pro官方渲染图首度公布:“双圆环”后摄模组抢眼