一? junit單元測試
1.1 單元測試作用
單元測試要滿足AIR原則,即
A: automatic 自動化;
I: Independent? 獨立性;
R:Repeatable 可重復;
2.單元測試必須使用assert來驗證
1.2 案例1 常規單元測試
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.測試
public class AppTest {@Testvoid 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 "優";}}
}
2.測試
class ScoreDemoTest
{@Testvoid scoreLevel(){ScoreDemo scoreDemo = new ScoreDemo();assertEquals("弱",scoreDemo.scoreLevel(52));}@Testvoid scoreLevelv2(){ScoreDemo scoreDemo = new ScoreDemo();assertEquals("差",scoreDemo.scoreLevel(62));}@Testvoid scoreLevelv3(){ScoreDemo scoreDemo = new ScoreDemo();assertEquals("中",scoreDemo.scoreLevel(80));}@Testvoid scoreLevelv4(){ScoreDemo scoreDemo = new ScoreDemo();assertThrows(IllegalArgumentException.class,() -> scoreDemo.scoreLevel(-7));}
}
查看測試報告:對應覆蓋率
1.4?案例3?BeforeEach,BeforeAfterall
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.測試?
class CalcDemoTestV2
{CalcDemo calcDemo = null;static StringBuffer stringBuffer = null;@BeforeAllstatic void m1(){stringBuffer = new StringBuffer("abc");System.out.println("===============: "+stringBuffer.length());}@AfterAllstatic void m2(){System.out.println("===============: "+stringBuffer.append(" ,end").toString());}@BeforeEachvoid setUp(){System.out.println("----come in BeforeEach");calcDemo = new CalcDemo();}@AfterEachvoid tearDown(){System.out.println("----come in AfterEach");calcDemo = null;}@Testvoid add(){assertEquals(5,calcDemo.add(1,4));assertEquals(5,calcDemo.add(2,3));}@Testvoid sub(){assertEquals(5,calcDemo.sub(10,5));}
}
3.結果
1.5?案例4? junit+反射+注解實現測試
1.定義注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AtguiguTest
{
}
2.定義調用類
public class CalcHelpDemo
{public int mul(int x ,int y){return x * y;}@AtguiguTestpublic int div(int x ,int y){return x / y;}@AtguiguTestpublic void thank(int x ,int y){System.out.println("3ks,help me test bug");}
}
3.定義測試類
@Slf4j
public class AutoTestClient
{public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException{//家庭作業,抽取一個方法,(class,p....)CalcHelpDemo calcHelpDemo = new CalcHelpDemo();int para1 = 10;int para2 = 0;Method[] methods = calcHelpDemo.getClass().getMethods();AtomicInteger bugCount = new AtomicInteger();// 要寫入的文件路徑(如果文件不存在,會創建該文件)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"+"出現了異常"+"\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("異常數:"+bugCount.get()+"\n", filePath, "UTF-8");}}}}
}
4.查看結果
1.6?案例5? web工程單元測試
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.啟動類
@SpringBootApplication
public class App
{public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println( "Hello World!" );}
}
4.測試類
@SpringBootTest
public class MemberTest {@Resource //真實調用,落盤mysql-MQ=redis。。。。測試條件充分的情況下private MemberService memberService1;// @Test
// void m1()
// {
// String result = memberService1.add(2);
// assertEquals("ok",result);
//
// System.out.println("----m1 over");
// }@MockBeanprivate 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");//不真的進入數據庫/MQ,不落盤,改變return
//
// String result = memberService2.add(3);
// assertEquals("ok",result);
//
// System.out.println("----m2_WithMockRule over");
// }
@SpyBean //有規則按照規則走,沒有規則走真實
private MemberService memberService3;@Testvoid 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);//跨部門調用,不是寫代碼,累的是心,協調工作。 zzyybs@126.comSystem.out.println("----over");}
}
4.結果