本文講解的主要是有效和單元的思想,並非說如何編寫單元測試,用於改善和提升開發效率、編碼風格、編碼可讀性和單測效率,不盲目追求覆蓋率。java
如今不少單元測試只是利用@Test註解把代碼或者整個請求接口內的business作測試redis
單測的過程就不少查數據庫的方法,可是不必每次都測sql,由於sql測一遍都應該是正確的。spring
未明確單元測試由開發負責。單元測試是用於維護代碼邏輯不被修改或者,修改了也不出錯,不是測試的事情。sql
單測代碼啓動速度、效率過低數據庫
沒有在各個環境整個工程單元測試經過json
方法寫的很大,行數不少,邊update邊作邏輯設計模式
不少公司盲目追求覆蓋率網絡
主要關鍵字: 有效、單元框架
樣例:分佈式
public void updateUser(String userName,Integer age) {
// 校驗
if (StringUtils.isEmpty(userName)) {
throw new RuntimeException();
}
// redis分佈式鎖
getRedis();
// 查詢主表
selectUser();
// 查詢出採買計劃Detail
selectUserDetail();
// 對數據進行處理
calculateUserDetailInfo();
// 更新主表
updatePuchasePlanDb();
// 更新detail表
updatePuchasePlanDbDetail();
}
複製代碼
假設上述updateUser是一個Controller下的第一個business邏輯入口,用於更新用戶信息,不少人的單元測試就會從updateUser這個方法開始作單元測試。可是這樣就不符合有效、單元的理念。
private void calculateUserDetailInfo() {
// 更改公司與關聯上下級關係
changeCompany();
// 更改組與關聯上下級關係
changeGroup();
// 更改部門與關聯上下級關係
changeDeptment();
}
複製代碼
錯誤編碼案例:
private void calculateBrand() {
for (int i = 0; i < new ArrayList<>().size(); i++) {
for (int i1 = 0; i1 < new ArrayList<>().size(); i1++) {
if (new Integer(1)==1) {
} else {
}
}
}
}
複製代碼
這樣的代碼就不符合單元的概念,至少把第二個for循環寫在另一個方法裏,由於單元測試中,認爲測試循環中一次是正確的,就斷言循環中每次都大機率正確。
public Integer logic2(Integer num) throws Exception {
try {
num = this.purchasePlanDetailBusinessImpl.method(num);
} catch (RuntimeException e) {
throw new Exception();
}
return ++num;
}
複製代碼
則對應編寫:
/** * 測試異常場景 */
@Test(expected = Exception.class)
public void testMethodOnException() {
Integer method = this.purchasePlanBusinessImpl.logic(null);
}
複製代碼
不少人的單元測試都是最後print一下,在console裏面看日誌或者debug看看是否正確,可是這樣不足夠。
以下,而不是直接判斷是否爲空或輸出到終端
@Test
public void testMethodOnNormal() {
Integer method = this.purchasePlanBusinessImpl.method(1);
Assert.assertTrue(method == 2);
}
複製代碼
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version><!--$NO-MVN-MAN-VER$ -->
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.7.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.7.RELEASE</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.7.RELEASE</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
</dependencies>
複製代碼
@RunWith(MockitoJUnitRunner.class)
public class PurchasePlanBusinessImplTest {
@InjectMocks
private DoSomeBusinessImpl purchasePlanBusinessImpl;
@Mock
private DoSomeDetailBusinessImpl purchasePlanDetailBusinessImpl;
/** * 正常流程 */
@Test
public void testMethodOnNormal() {
Integer method = this.purchasePlanBusinessImpl.method(1);
Assert.assertTrue(method == 2);
}
/** * 在某些場景 */
@Test
public void testMethodOnXX() {
when(this.purchasePlanDetailBusinessImpl.method(anyInt())).thenReturn(1);
Integer method = this.purchasePlanBusinessImpl.logic(1);
Assert.assertTrue(method == 3);
}
複製代碼