单元测试简介:
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
单元测试与集成测试:
集成测试(也叫组装测试,联合测试)是单元测试的逻辑扩展。它最简单的形式是:把两个已经测试过的单元组合成一个组件,测试它们之间的接口。以java语音为例,一段程序涉及到很多的外部依赖,比如依赖第三方接口,依赖数据库连接,集成测试可以很好的完成整个功能的测试。单元测试仅仅关注于模块。
黑盒测试与白盒测试:
白盒测试也称为结构测试,主要用于检测软件编码过程中的错误。程序员的编程经验、对编程软件的掌握程度、工作状态等因素都会影响到编程质量,导致代码错误。
黑盒测试又称为功能测试,主要检测软件的每一个功能是否能够正常使用。在测试过程中,将程序看成不能打开的黑盒子,不考虑程序内部结构和特性的基础上通过程序接口进行测试,检查程序功能是否按照设计需求以及说明书的规定能够正常打开使用。
单元测试其实就是属于一种白盒测试,需要我们编码了解内部结构,仅仅关注于给定输入,输出是否正确,功能是否正常,这个属于黑盒测试。
单元测试的一般流程:
Calculator类和它对应的测试类如下:
Calculator类:
package com.example.andy.service;
public class Calculator {
public int add(int a, int b){
return a + b;
}
public int subtract(int a, int b){
return a - b;
}
public int divide(int a, int b){
return a/b;
}
public int multiply(int a, int b){
return a * b;
}
}
CalculatorTest类:
package com.example.andy.service;
import org.junit.Assert;
import org.junit.function.ThrowingRunnable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class CalculatorTest {
Calculator calculator;
@BeforeEach
public void init(){
this.calculator = new Calculator();
}
@Test
public void addTest(){
int givenA = 1, givenB = 2;
int actualResult = this.calculator.add(givenA, givenB);
int expectedResult = 3;
Assert.assertEquals(expectedResult, actualResult);
}
@Test
public void substractTest(){
int givenA = 2,givenB = 1;
int actualResult = this.calculator.subtract(givenA, givenB);
int expectedRult = 1;
Assert.assertEquals(expectedRult, actualResult);
}
@Test
public void multiplyTest(){
int givenA = 2, givenB = 2;
int actualResult = this.calculator.multiply(givenA,givenB);
int expectedResult = 4;
Assert.assertEquals(expectedResult, actualResult);
}
@Test
public void dividTest(){
int givenA = 2, givenB = 1;
int actualResult = this.calculator.divide(givenA,givenB);
int expectedResult = 2;
Assert.assertEquals(expectedResult, actualResult);
}
@Test
public void dividTestThrowsException(){
Assert.assertThrows(ArithmeticException.class, new ThrowingRunnable() {
@Override
public void run() throws Throwable {
new Calculator().divide(2,0);
}
});
}
@Test
public void dividTestThrowsExceptionWithLambda(){
Assert.assertThrows(ArithmeticException.class, () -> new Calculator().divide(2,0));
}
}
异常测试:
这里对Calculor里除数为零的异常进行模拟:
@Test
public void dividTestThrowsException(){
Assert.assertThrows(ArithmeticException.class, new ThrowingRunnable() {
@Override
public void run() throws Throwable {
new Calculator().divide(2,0);
}
});
}
@Test
public void dividTestThrowsExceptionWithLambda(){
Assert.assertThrows(ArithmeticException.class, () -> new Calculator().divide(2,0));
}
Mockito和PowerMock
日常开发工作中,我们不可能只写这些简单的,没有依赖的单元测试,对于一些复杂的模块,这时就需要借助Mockito进行代码mock,Mockito可以完成大多数的单元测试,但是对于一些静态类或者内部方法这个时候需要借助PowerMock进行mock。具体可以参照下方链接,我觉得写的很好,就在这边引用。
Mockito和PowerMock的使用