一 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
{
@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 "优";
}
}
}
2.测试
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));
}
}
查看测试报告:对应覆盖率
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;
@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.结果
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;
}
@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.定义测试类
@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");
// }
@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");//不真的进入数据库/MQ,不落盘,改变return
//
// String result = memberService2.add(3);
// assertEquals("ok",result);
//
// System.out.println("----m2_WithMockRule over");
// }
@SpyBean //有规则按照规则走,没有规则走真实
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);
//跨部门调用,不是写代码,累的是心,协调工作。 zzyybs@126.com
System.out.println("----over");
}
}
4.结果