假设你有一个像这样的公共方法
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)
{
}
}
}
所以回到我的观点。 我想知道单元测试是否应该测试断言。 如果是这样,我会朝着正确的方向前进吗? 如果没有,如何在没有单元测试的情况下防止意外删除断言代码?
有趣的问题。
在我看来,如果你想测试 x
或y
明显不在范围内的情况,你应该抛出IllegalArgumentException
而不是使用assert
。 另一方面,你没有方法注释告诉调用者这个方法x
或y
必须在一个范围内。 因此,如果您从调用者的角度看到它,您根本没有权利断言。 :-P
我会使用assert
来检查我没有单元测试的前置条件。 但另一方面,您应该对该示例进行单元测试。
在一天结束时, assert
抛出一个RuntimeException
,并且 - 正如你所说 - 只在编译器标志的开发时间内。 那么为什么不简单地使用IllegalArgumentException
,这似乎是完美的。 并且请给方法的调用者提供提示,在这种情况下,它会被@throws
注释抛出。
我的结论:只要你有良好的单元测试覆盖率, assert
就没用了。 只有在开发过程中进行手动测试才能检查您不想要的前置条件,或者可以编写明确的单元测试。
如果使用-ea
java命令参数打开assert
功能,则始终可以测试assert
功能。
assert
抛出java.lang.AssertionError
。
单元测试应测试行为,而不是实现 。 因此,如果未在合同(JavaDoc)中明确定义asert行为,则不应对其进行测试。
assert
很无用,几乎从未在真实系统中使用过。