我有以下课程:public class Game { @Getter private String gameId; private String player1Id; private String player2Id; private String currentPlayer; private Board board; public Game() { board = new Board(); gameId = UUID.randomUUID().toString(); } public void joinGame(String playerUUID) { if (player1 == null) { player1 = playerUUID; currentPlayer = player1; } else if (player2 == null) { player2 = playerUUID; } else { throw new IllegalArgumentException("Cannot join"); } } .....}我想测试 joinGame() 方法中的逻辑:@Testvoid testJoinGame() { String player1Id = UUID.randomUUID().toString(); String player2Id = UUID.randomUUID().toString(); game.joinGame(player1Id); game.joinGame(player2Id); // this won't compile of course as fields are private assertEquals(player1Id, game.player1Id); assertEquals(player2Id, game.player2Id); assertEquals(player1Id, game.currentPlayer);}正如我经常读到的那样,在我的 JUnit 测试中我不应该做两件坏事: 1. 更改字段的可见性以使测试工作。2. 使用反射来获取私有字段的值。(我可以看到这两种方法在我从事的项目中被大量使用,但我们假设它们没有)。另外,我有时会读到,如果我想测试我的私有字段,那么这意味着该类的接口定义错误。但我想说,在这个例子中,情况并非如此:两个用户 ID 都只在类内部使用,不需要公开它们。我仍然想确保顺序是正确的:第一个尝试加入游戏的用户将是玩家 1(+ 他/她将是当前用户,例如将迈出第一步),第二个 - 玩家 2。我想问一下测试这种方法的正确解决方案是什么?
2 回答
烙印99
TA贡献1829条经验 获得超13个赞
有两种明显的方法。
测试实际使用这些值的位置。如果变量不在类外使用,为什么它们在那里?在提供的代码中,您只需要测试您是否获得了
IllegalArgumentException适当的代码。添加“获取”方法。
我更喜欢第一个。
扬帆大鱼
TA贡献1799条经验 获得超9个赞
我同意 Tom Hawtin 的回答,但我会把它们翻过来这么说:
单元测试通常应该避免查看被测类的内部实现细节。他们应该测试类如何与抽象边界之外的事物交互。
如果您在单元测试中查看“盒子内部”,那么如果实现发生更改,测试可能会不必要地中断。是的,您可以修复测试,但是您会遇到知道非测试代码是否也被破坏的问题。
另一方面,查看“盒子内部”可能会更容易编写测试用例。如果您决定采用这种方法:
添加单元测试用例可以使用的 getter 将允许其他代码依赖于实现细节。这是一个坏主意,即使 getter 是以防止修改的方式实现的。(您仍然有潜在的不想要的耦合,并且对您的类实现细节的更改会破坏事情)。
也可以使用反射从测试用例中检查私有字段。这很丑陋,但可以说比 getter 更好,因为“普通”代码不会这样做。实现更改仍然可能破坏单元测试......但只有单元测试。
添加回答
举报
0/150
提交
取消
