【问题标题】:How to assert that a proper value was assigned to a private field?如何断言为私有字段分配了适当的值?
【发布时间】:2018-12-10 02:07:18
【问题描述】:

我有以下课程:

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()方法中的逻辑:

@Test
void 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。

我想问一下测试这种方法的正确解决方案是什么?

【问题讨论】:

    标签: java testing junit5


    【解决方案1】:

    有两种明显的方法。

    • 测试实际使用这些值的位置。如果变量不在类外使用,为什么它们在那里?在提供的代码中,您只需要测试您是否获得了正确的IllegalArgumentException

    • 添加“get”方法。

    我更喜欢第一个。

    【讨论】:

    • 感谢您的回答。添加 get 方法不会破坏封装吗?如果我可以获得字符串的链接,那么我可以更改它们的值。
    • @Nikolai 仅此而已。 Strings 是不可变的。
    【解决方案2】:

    我同意 Tom Hawtin 的回答,但我会把它们翻过来这么说:

    • 单元测试通常应避免查看被测类的内部实现细节。他们应该测试类如何与抽象边界之外的事物交互。

    • 如果您在单元测试中查看“框内”,那么如果实现发生更改,测试可能会不必要地中断。是的,你可以修复测试,但是你会遇到问题,知道非测试代码是否也被破坏了。

    另一方面,查看“盒子内部”可能可以更轻松地编写测试用例。如果您决定采用这种方法:

    • 添加单元测试用例可以使用的 getter 将允许其他代码依赖于实现细节。这是一个坏主意,即使 getter 是以防止修改的方式实现的。 (您仍然有潜在的不想要的耦合,并且对类实现细节的更改会破坏事情)。

    • 还可以使用反射从测试用例中检查私有字段。这,但可以说比 getter 更好,因为“普通”代码不会这样做。实现更改仍然可能会破坏单元测试......但只有单元测试。

    【讨论】:

      猜你喜欢
      • 2013-02-23
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多