首页 文章

当单元测试方法有断言而不是异常时,最佳做法是什么?

提问于
浏览
4

假设你有一个像这样的公共方法

public Sprite spriteAt(int x, int y) 
{
    assert withinBorders(x, y) : "PRE: x and y should be inside the borders";

    return tileAt(x, y).topSprite();
}

public Sprite spriteAt(int x, int y)
{
    if (!withinBorders(x, y)) throw new InvalidArgumentException();

    return tileAt(x, y).topSprite();
}

在底部的情况下,我通常会有一个单元测试用例,它检查当给出x和/或y的无效值时是否抛出异常,如:

@Test(expected = InvalidArgumentException.class)
public void SpriteAt_InvalidX_ThrowsInvalidArgumentException()
{
    sut.spriteAt(-100, 0);
}

此测试用例是为了确保在方法中实现参数验证逻辑 .

但是,对于顶部的断言方法,我不确定我应该做什么 . 断言不是 生产环境 代码,我认为这意味着我不必测试断言 .

另一方面,我认为单元测试应该在方法中的逻辑更改失败时通知开发人员 . 如果我没有编写测试用例来检查是否存在检查无效参数的断言(就像我对异常方法所做的那样),那么当我意外删除代码断言行时,我可能没有意识到我犯了一个错误 .

因此,我想要做的是检查断言是否已经到位,如果在启用断言的情况下运行junit并且在未启用断言时不执行任何操作 . 下面的代码将包含伪代码 .

@Test
public void SpriteAt_InvalidX_AssertionThrowsException()
{
    if (assertion is enabled)
    {
        try
        {
             sut.spriteAt(-100, 0);
             fail();    
        }
        catch (AssertionFailureException e)
        {
        }
    }
}

所以回到我的观点 . 我想知道单元测试是否应该测试断言 . 如果是这样,我会朝着正确的方向前进吗?如果没有,如何在没有单元测试的情况下防止意外删除断言代码?

2 回答

  • 0

    有趣的问题 .

    在我看来,如果你想测试 xy 明显不在范围内的情况,你应该抛出 IllegalArgumentException 而不是使用 assert . 另一方面,您没有方法注释告诉调用者此方法 xy 必须在一个范围内 . 因此,如果您从调用者的角度看到它,您根本没有权利断言 . :-P

    我会使用 assert 来检查我没有单元测试的前置条件 . 但另一方面,您应该对该示例进行单元测试 .

    在一天结束的时候 assert 也会抛出一个 RuntimeException ,而且正如你所说的那样 - 仅在编译器标志的开发时间内 . 那么为什么不简单地使用 IllegalArgumentException ,这似乎是完美的 . 并且请给方法的调用者提供提示,在这种情况下,它会被 @throws 注释抛出 .

    我的结论是:只要你有良好的单元测试覆盖率,_1536813就没用了 . 它是 only good for manual testing during development 来检查您不想要的前置条件或者可以为其编写显式单元测试 .

  • 2

    如果使用 -ea java命令参数将其打开,则始终可以测试 assert 功能 .

    assert 抛出 java.lang.AssertionError .

    Unit tests should test the behavior, not the implementation . 因此,如果未在 Contract (JavaDoc)中明确定义asert行为,则不应对其进行测试 .

    assert is pretty useless and is almost never used in real systems.

相关问题