java學(xué)習(xí)之junit單元測(cè)試案例(經(jīng)典版)
一 junit單元測(cè)試
1.1 單元測(cè)試作用
單元測(cè)試要滿足AIR原則,即
A: automatic 自動(dòng)化;
I: Independent 獨(dú)立性;
R:Repeatable 可重復(fù);
2.單元測(cè)試必須使用assert來驗(yàn)證
1.2 案例1 常規(guī)單元測(cè)試
1.代碼
public class CalcDemo { public int add(int x ,int y) { return x + y; //return x * y; } public int sub(int x ,int y) { return x - y; } }
2.測(cè)試
public class AppTest { @Test void sub() { CalcDemo calcDemo = new CalcDemo(); int retValue = calcDemo.sub(2, 2); assertEquals(0,retValue); System.out.println(""); } }
1.3 案例2 單元覆蓋率Coverage*
1.代碼
public class ScoreDemo { public String scoreLevel(int score) { if(score <= 0) { throw new IllegalArgumentException("缺考"); } else if (score < 60) { return "弱"; } else if (score < 70) { return "差"; } else if (score <= 80) { return "中"; } else if (score < 90) { return "良"; } else { return "優(yōu)"; } } }
2.測(cè)試
class ScoreDemoTest { @Test void scoreLevel() { ScoreDemo scoreDemo = new ScoreDemo(); assertEquals("弱",scoreDemo.scoreLevel(52)); } @Test void scoreLevelv2() { ScoreDemo scoreDemo = new ScoreDemo(); assertEquals("差",scoreDemo.scoreLevel(62)); } @Test void scoreLevelv3() { ScoreDemo scoreDemo = new ScoreDemo(); assertEquals("中",scoreDemo.scoreLevel(80)); } @Test void scoreLevelv4() { ScoreDemo scoreDemo = new ScoreDemo(); assertThrows(IllegalArgumentException.class,() -> scoreDemo.scoreLevel(-7)); } }
查看測(cè)試報(bào)告:對(duì)應(yīng)覆蓋率
1.4 案例3 BeforeEach,BeforeAfterall
1.4.1 Api說明
1.4.2 案例操作
1.代碼
public class CalcDemo { public int add(int x ,int y) { return x + y; //return x * y; } public int sub(int x ,int y) { return x - y; } }
2.測(cè)試
class CalcDemoTestV2 { CalcDemo calcDemo = null; static StringBuffer stringBuffer = null; @BeforeAll static void m1() { stringBuffer = new StringBuffer("abc"); System.out.println("===============: "+stringBuffer.length()); } @AfterAll static void m2() { System.out.println("===============: "+stringBuffer.append(" ,end").toString()); } @BeforeEach void setUp() { System.out.println("----come in BeforeEach"); calcDemo = new CalcDemo(); } @AfterEach void tearDown() { System.out.println("----come in AfterEach"); calcDemo = null; } @Test void add() { assertEquals(5,calcDemo.add(1,4)); assertEquals(5,calcDemo.add(2,3)); } @Test void sub() { assertEquals(5,calcDemo.sub(10,5)); } }
3.結(jié)果
1.5 案例4 junit+反射+注解實(shí)現(xiàn)測(cè)試
1.定義注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AtguiguTest { }
2.定義調(diào)用類
public class CalcHelpDemo { public int mul(int x ,int y) { return x * y; } @AtguiguTest public int div(int x ,int y) { return x / y; } @AtguiguTest public void thank(int x ,int y) { System.out.println("3ks,help me test bug"); } }
3.定義測(cè)試類
@Slf4j public class AutoTestClient { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { //家庭作業(yè),抽取一個(gè)方法,(class,p....) CalcHelpDemo calcHelpDemo = new CalcHelpDemo(); int para1 = 10; int para2 = 0; Method[] methods = calcHelpDemo.getClass().getMethods(); AtomicInteger bugCount = new AtomicInteger(); // 要寫入的文件路徑(如果文件不存在,會(huì)創(chuàng)建該文件) String filePath = "BugReport"+ (DateUtil.format(new Date(), "yyyyMMddHHmmss"))+".txt"; for (int i = 0; i < methods.length; i++) { if (methods[i].isAnnotationPresent(AtguiguTest.class)) { try { methods[i].invoke(calcHelpDemo,para1,para2);//放行 } catch (Exception e) { bugCount.getAndIncrement(); log.info("異常名稱:{},異常原因:{}",e.getCause().getClass().getSimpleName(),e.getCause().getMessage()); FileUtil.writeString(methods[i].getName()+"\t"+"出現(xiàn)了異常"+"\n", filePath, "UTF-8"); FileUtil.appendString("異常名稱:"+e.getCause().getClass().getSimpleName()+"\n", filePath, "UTF-8"); FileUtil.appendString("異常原因:"+e.getCause().getMessage()+"\n", filePath, "UTF-8"); }finally { FileUtil.appendString("異常數(shù):"+bugCount.get()+"\n", filePath, "UTF-8"); } } } } }
4.查看結(jié)果
1.6 案例5 web工程單元測(cè)試
1.6.1 mock和spy的區(qū)別聯(lián)系
1.6.2 案例
1.pom配置
<!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2.處理類
@Service public class MemberService { public String add(Integer uid) { System.out.println("---come in addUser,your uid is: "+uid); if (uid == -1) { throw new IllegalArgumentException("parameter is negative。。。。"); } return "ok"; } public int del(Integer uid) { System.out.println("---come in del,your uid is: "+uid); return uid; } }
3.啟動(dòng)類
@SpringBootApplication public class App { public static void main( String[] args ) { SpringApplication.run(App.class, args); System.out.println( "Hello World!" ); } }
4.測(cè)試類
@SpringBootTest public class MemberTest { @Resource //真實(shí)調(diào)用,落盤mysql-MQ=redis。。。。測(cè)試條件充分的情況下 private MemberService memberService1; // @Test // void m1() // { // String result = memberService1.add(2); // assertEquals("ok",result); // // System.out.println("----m1 over"); // } @MockBean private MemberService memberService2; // @Test // void m2_NotMockRule() // { // String result = memberService2.add(2); // assertEquals("ok",result); // // System.out.println("----m2_NotMockRule over"); // } // @Test // void m2_WithMockRule() // { // when(memberService2.add(3)).thenReturn("ok");//不真的進(jìn)入數(shù)據(jù)庫/MQ,不落盤,改變r(jià)eturn // // String result = memberService2.add(3); // assertEquals("ok",result); // // System.out.println("----m2_WithMockRule over"); // } @SpyBean //有規(guī)則按照規(guī)則走,沒有規(guī)則走真實(shí) private MemberService memberService3; @Test void m3() { when(memberService3.add(2)).thenReturn("ok"); String result = memberService3.add(2); System.out.println("----add result: "+result); Assertions.assertEquals("ok",result); int result2 = memberService3.del(3); System.out.println("----del result2: "+result2); Assertions.assertEquals(3,result2); //跨部門調(diào)用,不是寫代碼,累的是心,協(xié)調(diào)工作。 zzyybs@126.com System.out.println("----over"); } }
4.結(jié)果
總結(jié)
到此這篇關(guān)于java學(xué)習(xí)之junit單元測(cè)試的文章就介紹到這了,更多相關(guān)java junit單元測(cè)試案例內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入探究 spring-boot-starter-parent的作用
這篇文章主要介紹了spring-boot-starter-parent的作用詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,感興趣的小伙伴可以跟著小編一起來學(xué)習(xí)一下2023-05-05解決springmvc+mybatis+mysql中文亂碼問題
這篇文章主要介紹了解決java中springmvc+mybatis+mysql中文亂碼問題的相關(guān)資料,需要的朋友可以參考下2015-09-09SpringBoot讀取properties配置文件中的數(shù)據(jù)的三種方法
本文主要介紹了SpringBoot讀取properties配置文件中的數(shù)據(jù)的三種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06springboot導(dǎo)入多個(gè)配置文件的方法實(shí)踐
Spring Boot 2.4.x引入了新的配置導(dǎo)入方式,通過spring.config.import屬性可以靈活地導(dǎo)入多種類型的配置文件,本文就來介紹一下,感興趣的可以了解一下2024-11-11Intellij IDEA遠(yuǎn)程debug教程實(shí)戰(zhàn)和要點(diǎn)總結(jié)(推薦)
這篇文章主要介紹了Intellij IDEA遠(yuǎn)程debug教程實(shí)戰(zhàn)和要點(diǎn)總結(jié)(推薦),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03Java的@Transactional、@Aysnc、事務(wù)同步問題詳解
這篇文章主要介紹了Java的@Transactional、@Aysnc、事務(wù)同步問題詳解,現(xiàn)在我們需要在一個(gè)業(yè)務(wù)方法中插入一個(gè)用戶,這個(gè)業(yè)務(wù)方法我們需要加上事務(wù),然后插入用戶后,我們要異步的方式打印出數(shù)據(jù)庫中所有存在的用戶,需要的朋友可以參考下2023-11-11java父子節(jié)點(diǎn)parentid樹形結(jié)構(gòu)數(shù)據(jù)的規(guī)整
這篇文章主要介紹了java父子節(jié)點(diǎn)parentid樹形結(jié)構(gòu)數(shù)據(jù)的規(guī)整,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07