通常,在没有特定框架支持下,我们在对一个方法进行单元测试的时候,无外乎是使用分支判断、异常处理、流程控制等来控制代码的执行,通过程序输出来表示方法的执行成功和失败。这样存在的最大问题就是我们每执行完一个单测之后,都要去控制台看输出才知道单元测试有没有成功,这明显是不合理的,因为单元测试是需要自动化执行的,程序没办法帮我们检查输出是否正确的。
单元测试框架就解决了这个问题,一旦使用了框架,加入单元测试相对来说会简单许多。通常,Java中常用的单元测试框架包含三个功能:测试工具、测试套件、测试运行器。
- 测试工具:测试工具是一整套固定的工具用于基线测试。测试工具的目的是为了确保测试能够在共享且固定的环境中运行,因此保证测试结果的可重复性。一般负责初始化测试环境、准备测试数据和测试数据清理。
- 测试套件: 测试套件意味捆绑几个测试案例并且同时运行。
- 测试运行器: 用于执行测试案例,一般负责调用需要被测试的单元、收集结果、并与期望值比较。
JUnit示例Demo
/**
* 使用JUNIT进行单元测试的一般步骤是:
*
* step1:创建一个测试类,下面的列子中是CalculateServiceImplTest
*
* step2:向测试类中添加名为 testAdd() 的方法。
*
* step3:向方法:上添加 Annotaion @Test。
*
* step4:执行测试条件并且应用 Junit 的 assertEquals API 来检查。
*
*
*/
public class CalculateServiceImplTest {
public static final Logger logger = LoggerFactory.getLogger(CalculateServiceImplTest.class);
private CalculateService calculateService;
@Before
public void setUp() throws Exception {
logger.info("begin to test...");
calculateService = new CalculateServiceImpl();
}
@Test
public void testAdd(){
Assert.assertEquals(calculateService.add(2,2),4);
}
@After
public void tearDown() throws Exception {
logger.info("end to test...");
}
}
JUnit中的Assert
public class Assert extends java.lang.Object
这个类提供了一系列的编写测试的有用的声明方法。只有失败的声明方法才会被记录。
-
void assertEquals(boolean expected, boolean actual)
- 检查两个变量或者等式是否平衡
-
void assertFalse(boolean condition)
- 检查条件是假的
-
void assertNotNull(Object object)
- 检查对象不是空的
-
void assertNull(Object object)
- 检查对象是空的
-
void assertTrue(boolean condition)
- 检查条件为真
-
void fail()
- 在没有报告的情况下使测试不通过
这些方法我就不一一介绍了,相信我的读者们都能看懂并在平时开发中用的到,还是比较容易理解的。
Assert可以用来判断方法的真是结果和预期结果是否一样。是我们在写单元测试中用到最多的一个api。
JUnit中的注解
@BeforeClass
:针对所有测试,只执行一次,且必须为static void@Before
:初始化方法@Test
:测试方法,在这里可以测试期望异常和超时时间@After
:释放资源@AfterClass
:针对所有测试,只执行一次,且必须为static void@Ignore
:忽略的测试方法
一个单元测试类执行顺序为:
@BeforeClass
–> @Before
–> @Test
–> @After
–> @AfterClass
每一个测试方法的调用顺序为:
@Before
–> @Test
–> @After
1.@BeforeClass 和 @AfterClass 对于那些比较“昂贵”的资源的分配或者释放来说是很有效的,因为他们只会在类中被执行一次。相比之下对于那些需要在每次运行之前都要初始化或者在运行之后 都需要被清理的资源来说使用@Before和@After同样是一个比较明智的选择;
2.如果类里面可以有多个注解过@Before和@After的方法,它们的执行顺序是未知的;
3.@BeforeClass @AfterClass注解是junit提供的另外的两个注解,必须设置在public 静态方法之上,表示在class加载之前执行,这样设置的方法只会执行一次,而@Before @After则会再每次test之前/之后执行;
4.在JUnit4中,如果测试类继承了TestCase类,那么所有的Annotation都不会起作用。
时间测试
如果一个测试用例比起指定的毫秒数花费了更多的时间,那么 Junit 将自动将它标记为失败。timeout 参数和 @Test
注释一起使用。现在让我们看看活动中的 @test(timeout)。
@Test(timeout = 1000)
public void testTimeoutSuccess() {
// do nothing
}
异常测试
你可以测试代码是否它抛出了想要得到的异常。expected 参数和 @Test 注释一起使用。现在让我们看看活动中的 @Test(expected)。
@Test(expected = NullPointerException.class)
public void testException() {
throw new NullPointerException();
}