关于单元测试的指导原则和最佳做法
本节概述了关于单元测试的指导原则和最佳做法。
单元测试是无需运行方法服务器即可执行的测试。
在开发计算机上本地执行单元测试时,请确保在方法服务器停止的情况下成功运行单元测试。
所有单元测试名称均应为 ****Test.java
编写彼此独立的测试用例。
旨在通过单元测试覆盖所有路径。
使用与生产数据接近的测试数据。
请确保单元测试完全在内存中运行。例如,不要编写需要发出 HTTP 请求、访问数据库或从文件系统读取的单元测试。
旨在让每个单元测试方法都只执行一个断言。
以包括待测试的方法和条件的约定命名单元测试。例如,如果正在测试的方法为 'encode(bytes[])',并且存在用于测试所有可能被传递的输入类型 (例如,null、空值、字节过多或过少等) 的测试用例,则针对各个用例编写单独的测试。
encode_nullBytes
encode_emptyBytes
encode_tooFewBytes
encode_tooManyBytes
encode_rightNumBytesencode_validBytes
请确保测试类与受测试生产类位于同一 Java 包中。
请确保测试代码与生产代码分开。
请勿在单元测试类构造函数中初始化;请改用 @Before 方法。
请勿在单元测试中使用 Thread.sleep
请使用最合适的断言方法:
使用 assertTrue(classUnderTest.methodUnderTest()) 而不是 assertEquals(true, classUnderTest.methodUnderTest())
使用 assertEquals(expectedReturnValue, classUnderTest.methodUnderTest()) 而不是 assertTrue(classUnderTest.methodUnderTest().equals(expectedReturnValue))
使用 assertEquals(expectedCollection, classUnderTest.getCollection()),而不是对集合大小和各个集合成员进行断言。
按正确的顺序放置断言参数。JUnit 断言的参数如下:
a. expected
b. actual
使用 assertEquals (expected, actual) 而不是 assertEquals (actual, expected)
请勿编写您自己的、仅用于通过测试的 catch 块。
// Don't do this - it's not necessary to write the try/catch!
@Test
public void foo_nine()
{
boolean wasExceptionThrown = false;
try
{
new Foo().foo(9);
}
catch (final IOException e)
{
wasExceptionThrown = true;
}
assertTrue(wasExceptionThrown);
}
// Do this instead
@Test(expected = IOException.class)
public void foo_nine() throws Exception
{
new Foo().foo(9);
}
在测试类中,请勿声明方法抛出任何特定类型的异常。
final class Foo
{
int foo(int i) throws IOException;
}
// Don't do this - the throws clause is too specific!
@Test
public void foo_seven() throws IOException
{
assertEquals(3, new Foo().foo(7));
}
相反,应声明测试方法可能会抛出任何异常:
// Do this instead
@Test
public void foo_seven() throws Exception
{
assertEquals(3, new Foo().foo(7));
}
编写测试时,请使用适当的注释。
如果正在测试的方法调用其他类的任何其他方法,则该 'called' 方法可能是模拟的候选方法。如果在未模拟 'called' 方法的情况下,测试成功运行且没有任何问题,则可能不需要模拟。存在一些需要模拟的示例,比如当 'called' 方法需要方法服务器执行操作时。
谨慎模拟类。模拟类时,现有方法或构造函数的原始实现将临时替换为模拟实现,这通常发生在单次测试期间。
这对您有帮助吗?