網(wǎng)站域名解析錯誤怎么辦seo與sem的關(guān)系
文章目錄
- 概要
- 首先看看junit和testng的區(qū)別
- 實踐篇
- 摸擬業(yè)務(wù)邏輯代碼
- 簡單對象
- 數(shù)據(jù)層摸擬類
- 業(yè)務(wù)邏輯層摸擬類
- 后臺任務(wù)摸擬類
- 基于spring+mock+junit
- 基于spring+mock+testng
- 示例的差異點
- junit與testng的主要變動不大,有以下幾個點需要注意
- 注解部分
- 在before,after中
- testng多出按配置執(zhí)行功能
- 附上關(guān)于mock 新舊寫法改進
- 小結(jié)
概要
本文作者之前寫單元測試都是使用junit
場景有以下三種場景
僅junit
spring+junit
mock+spring+junit
本文會用第三種場景寫簡單的實例列出junit和testng的代碼相關(guān)說明
并會將涉及的修改點一一說明
目的幫助大家了解testng及具體的切換方式
首先看看junit和testng的區(qū)別
JUnit和TestNG是兩種流行的Java測試框架,用于測試Java應用程序中的代碼。它們具有以下區(qū)別:
-
組織方式:JUnit使用Annotations來標注測試方法,而TestNG使用XML文件來組織測試。
-
支持的測試類型:JUnit 4支持單元測試,而TestNG支持功能測試、集成測試和端到端測試。
-
并發(fā)測試:TestNG支持并發(fā)測試,可以在同一時間運行多個測試用例,而JUnit不支持并發(fā)測試。
-
數(shù)據(jù)提供者:TestNG支持數(shù)據(jù)提供者,可以在不同參數(shù)上運行相同的測試用例,而JUnit不支持數(shù)據(jù)提供者。
-
測試套件:TestNG支持測試套件,可以組織不同的測試用例,而JUnit不支持測試套件。
-
依賴測試:TestNG支持依賴測試,可以在一組測試之前運行必需的測試,而JUnit不支持依賴測試。JUnit和TestNG是兩種流行的Java測試框架,用于測試Java應用程序中的代碼。它們具有以下區(qū)別:
實踐篇
摸擬業(yè)務(wù)邏輯代碼
場景,有三層以上代碼層次的業(yè)務(wù)場景,需要摸擬最底層數(shù)據(jù)層代碼
簡單對象
package com.riso.junit;/*** DemoEntity* @author jie01.zhu* date 2023/10/29*/
public class DemoEntity implements java.io.Serializable {private long id;private String name;public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "DemoEntity{" + "id=" + id + ", name='" + name + '\'' + '}';}}
數(shù)據(jù)層摸擬類
package com.riso.junit;import org.springframework.stereotype.Component;/*** DemoDaoImpl* @author jie01.zhu* date 2023/10/29*/
@Component
public class DemoDaoImpl {public int insert(DemoEntity demoEntity) {System.out.println("dao.insert:" + demoEntity.toString());return 1;}
}
業(yè)務(wù)邏輯層摸擬類
package com.riso.junit;import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** DemoServiceImpl* @author jie01.zhu* date 2023/10/29*/
@Service
public class DemoServiceImpl {@ResourceDemoDaoImpl demoDao;public int insert(DemoEntity demoEntity) {System.out.println("service.insert:" + demoEntity.toString());return demoDao.insert(demoEntity);}}
后臺任務(wù)摸擬類
package com.riso.junit;import org.springframework.stereotype.Component;/*** DemoTaskImpl* @author jie01.zhu* date 2023/10/29*/
@Component
public class DemoTaskImpl {DemoServiceImpl demoService;public int insert(DemoEntity demoEntity) {System.out.println("task.insert:" + demoEntity.toString());return demoService.insert(demoEntity);}
}
基于spring+mock+junit
maven依賴
<!-- test --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>3.12.4</version><scope>test</scope></dependency>
package com.riso.junit.test;import com.riso.junit.DemoDaoImpl;
import com.riso.junit.DemoEntity;
import com.riso.junit.DemoServiceImpl;
import com.riso.junit.DemoTaskImpl;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;/*** junit test* @author jie01.zhu* date 2023/10/29*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"}, inheritLocations = true)
public class Test1 {/*** 測試入口類*/@Resource@InjectMocksDemoTaskImpl demoTask;/*** mock的類的中間傳遞類*/@Resource@InjectMocksDemoServiceImpl demoService;/*** 被mock的類*/@MockDemoDaoImpl demoDao;@Testpublic void test1() {// 初始化mock環(huán)境MockitoAnnotations.openMocks(this);DemoEntity demoEntity = new DemoEntity();demoEntity.setId(1L);demoEntity.setName("name1");Mockito.doReturn(0).when(demoDao).insert(Mockito.any());int result = demoTask.insert(demoEntity);Assert.assertEquals(result, 0);}
}
基于spring+mock+testng
有二個測試類,測試參數(shù)不同,主要體現(xiàn)在單元測試外,控制二個測試類,按并發(fā)場景做簡單的集成測試
maven依賴
<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.14.3</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><version>2.4.13</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>3.12.4</version><scope>test</scope></dependency>
package com.riso.testng.test;import com.riso.testng.ContextConfig;
import com.riso.testng.DemoDaoImpl;
import com.riso.testng.DemoEntity;
import com.riso.testng.DemoTaskImpl;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;import javax.annotation.Resource;/*** junit test* @author jie01.zhu* date 2023/10/29*/
@SpringBootTest(classes = {ContextConfig.class})
@TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
public class Test1 extends AbstractTestNGSpringContextTests {/*** 測試入口類*/@ResourceDemoTaskImpl demoTask;/*** 被mock的類 選用spy方式 默認使用原生邏輯,僅mock的方法才被mock*/@SpyBeanDemoDaoImpl demoDao;@Testpublic void test1() {// 初始化mock環(huán)境MockitoAnnotations.openMocks(this);DemoEntity demoEntity = new DemoEntity();demoEntity.setId(1L);demoEntity.setName("name1");Mockito.doReturn(0).when(demoDao).insert(Mockito.any());int result = demoTask.insert(demoEntity);Assert.assertEquals(result, 0);}
}package com.riso.testng.test;import com.riso.testng.ContextConfig;
import com.riso.testng.DemoDaoImpl;
import com.riso.testng.DemoEntity;
import com.riso.testng.DemoTaskImpl;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;import javax.annotation.Resource;/*** junit test* @author jie01.zhu* date 2023/10/29*/
@SpringBootTest(classes = {ContextConfig.class})
@TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
public class Test2 extends AbstractTestNGSpringContextTests {/*** 測試入口類*/@ResourceDemoTaskImpl demoTask;/*** 被mock的類 選用spy方式 默認使用原生邏輯,僅mock的方法才被mock*/@SpyBeanDemoDaoImpl demoDao;@Testpublic void test2() {// 初始化mock環(huán)境MockitoAnnotations.openMocks(this);DemoEntity demoEntity = new DemoEntity();demoEntity.setId(2L);demoEntity.setName("name2");Mockito.doReturn(2).when(demoDao).insert(Mockito.any());int result = demoTask.insert(demoEntity);Assert.assertEquals(result, 2);}
}
testNg的 配置文件,也是執(zhí)行入口
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="test" parallel="tests" thread-count="2"><test name="test1" group-by-instances="true"><classes><class name="com.riso.testng.test.Test1"/></classes></test><test name="test2" group-by-instances="true"><classes><class name="com.riso.testng.test.Test2"></class></classes></test>
</suite>
運行方式如下:
示例的差異點
junit與testng的主要變動不大,有以下幾個點需要注意
注解部分
junit此處注解
@RunWith(SpringJUnit4ClassRunner.class)
testng不再使用此注解
需要繼承 org.springframework.test.context.testng.AbstractTestNGSpringContextTests
在before,after中
testng完全兼容,但會多出Suite ,它代替xml配置中,單元測試類之上的生命周期
testng多出按配置執(zhí)行功能
首先testng的單元測試可以與junit一樣,單獨運行
在這個基礎(chǔ)上,也能通過testng xml按配置運行,可以見上面的例子
附上關(guān)于mock 新舊寫法改進
以前要摸擬調(diào)用對象的跨二層以上類時,需要通過InjectMocks 做為中間傳遞,才能成功mock掉二層以上的類
換成spyBean后,不需要再使用InjectMocks ,會自動從注入中找到
這個小插曲也是我自己對以前mock的修正,一并附上
小結(jié)
通過以上說明,及示例
testng是完全兼容junit的,且改動很小
注解,斷言都是直接兼容的(只需要更換導入的包路徑既可)
當然,我不是為了使用而使用,一切都要建立上有需求的基礎(chǔ)上
junit對我來講,已經(jīng)滿足不了我的需求,
為了能夠編寫集成測試,同時復用已有的單元測試,我選擇了testng
希望以上分享,可以對讀都有用
朱杰
2023-10-29