Spring boot 单元测试:
常用的程序测试方法有:
1、直接通过在浏览器输入网址访问;
2、通过postman工具来测试;
3、通过编写python脚本来进行测试;
但这样经常会一测就要测一整块,相对单元测试来说定位问题比较麻烦,单元测试能帮助我们拆分方法,单独测试些关键的代码、功能,是日常开发中必备的技能,同时也是各大公司招技术人员的必要要求之一。但今天看了不少文章,也试了不少,发现即是很简单的东西自己也走了不少弯路,所以觉得很有必要把今天的练习写下来。
这里要说明一下,在单元测试里面在注入的时候,用Autowired和用new是有很大区别的,
@autowire跟XML方式注入类似,是Ioc容器负责创建新的实例,实例里可以有其他的依赖关系并也由springIoc容器负责注入,如果只是简单的new一个对象的话,新对象里面的所有变量依赖都是没有注入的,这样就失去了Ioc的意义。而且new的对象不能调用注入的其他类!!!
详细步骤:
Spring boot目录结构一般是固定的:
选中要测试的方法体右键:
会弹出新建测试类的框
上面一个是我测试建的,如果要新建应该选第二个:Create New Test...
上面是生成测试类的名称以及测试的一些属性,下面是选择你要放入的待测试的模块:
下面开始上代码:
Spring boot自带的测试基类(启动配置):
package com.ai.rai.group.workflow.application;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Project:bean_generator
* Author:hangke
* Date:2017/1/13
* Description://TODO add description here
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class BaseTestApplication
{
protected Logger logger = LoggerFactory.getLogger(this.getClass());
}
测试类启动入口(一般都有的,这边也贴一下吧):
package com.ai.rai.group.workflow.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* Project:html_template
* Author:hangke
* Date:2017/3/22
* Description://TODO add description here
*/
@SpringBootApplication
@ComponentScan(basePackages={"com.ai", "com.asiainfo"})
public class TestApplication
{
public static void main(String[] args)
{
SpringApplication.run(TestApplication.class,args);
}
}
待测试的Service方法就不贴了,根据自己的实际情况写逻辑就行;
测试类(使用依赖注入):
package com.ai.rai.group.workflow.service.impl;
import com.ai.rai.group.workflow.application.BaseTestApplication;
import com.ai.rai.group.workflow.entity.beans.TmWorkInst;
import com.ai.rai.group.workflow.service.IWorkFlowService;
import org.apache.commons.collections.bag.SynchronizedSortedBag;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import sun.tools.jar.Main;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
public class WorkFlowServiceImpllswTest extends BaseTestApplication {
//Service里面Dao用了依赖注入,这便不能用new对象的方式
@Autowired
IWorkFlowService workFlowServiceImpl;
@Test
public void selectWorkInstById() {
//这个用的之前写好的Service测试,
TmWorkInst workInst = new TmWorkInst();
List ss = workFlowServiceImpl.selectWorkInstById(workInst);
for (TmWorkInst o : ss)
System.out.println("==============="+o.toString());
}
}
控制台部分信息打印:
只是想学习自己简单调试下接口的同学,到这可以下课了;
正常的单元测试流程还需要加断言打印日志
加断言可以避免对数据库的误操作,以及缩短测试流程(断言失败就不再执行之后的代码了)
代码:
package com.ai.rai.group.workflow.service.impl;
import com.ai.rai.group.workflow.application.BaseTestApplication;
import com.ai.rai.group.workflow.entity.beans.TmWorkInst;
import com.ai.rai.group.workflow.service.IWorkFlowService;
import org.apache.commons.collections.bag.SynchronizedSortedBag;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import sun.tools.jar.Main;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class)
public class WorkFlowServiceImpllswTest extends BaseTestApplication {
//Service里面Dao用了依赖注入,这便不能用new对象的方式
@Autowired
IWorkFlowService workFlowServiceImpl;
@Test
public void selectWorkInstById() {
TmWorkInst workInst = new TmWorkInst();
List ss = workFlowServiceImpl.selectWorkInstById(workInst);
//添加断言(判空)
assertNull(ss);
for (TmWorkInst o : ss)
System.out.println("===============" + o.toString());
}
}
查看日志:
断言失败后后面的代码就没再执行了,比较正规和安全;
附上单元测试断言汇总:
出自:https://my.oschina.net/u/1418722/blog/340194
XCTFail(...)
任何尝试都会测试失败,...是输出的提示文字。(后面都是这样)
XCTAssertNil(expression, ...)
expression为空时通过,否则测试失败。
expression接受id类型的参数。
XCTAssertNotNil(expression, ...)
expression不为空时通过,否则测试失败。
expression接受id类型的参数。
XCTAssert(expression, ...)
expression为true时通过,否则测试失败。
expression接受boolean类型的参数。
XCTAssertTrue(expression, ...)
expression为true时通过,否则测试失败。
expression接受boolean类型的参数。
XCTAssertFalse(expression, ...)
expression为false时通过,否则测试失败。
expression接受boolean类型的参数。
XCTAssertEqualObjects(expression1, expression2, ...)
expression1和expression1地址相同时通过,否则测试失败。
expression接受id类型的参数。
XCTAssertNotEqualObjects(expression1, expression2, ...)
expression1和expression1地址不相同时通过,否则测试失败。
expression接受id类型的参数。
XCTAssertEqual(expression1, expression2, ...)
expression1和expression1相等时通过,否则测试失败。
expression接受基本类型的参数(数值、结构体之类的)。
XCTAssertNotEqual(expression1, expression2, ...)
expression1和expression1不相等时通过,否则测试失败。
expression接受基本类型的参数。
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, ...)
expression1和expression2之间的任何值都大于accuracy时,测试失败。
expression1、expression2、accuracy都为基本类型。
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, ...)
expression1和expression2之间的任何值都小于等于accuracy时,测试失败。
expression1、expression2、accuracy都为基本类型。
XCTAssertGreaterThan(expression1, expression2, ...)
expression1 <= expression2时,测试失败。
expression为基本类型
XCTAssertGreaterThanOrEqual(expression1, expression2, ...)
expression1 < expression2时,测试失败。
expression为基本类型
XCTAssertLessThan(expression1, expression2, ...)
expression1 >= expression2时,测试失败。
expression为基本类型
XCTAssertLessThanOrEqual(expression1, expression2, ...)
expression1 > expression2时,测试失败。
expression为基本类型
XCTAssertThrows(expression, ...)
expression没抛异常,测试失败。
expression为一个表达式
XCTAssertThrowsSpecific(expression, exception_class, ...)
expression没抛指定类的异常,测试失败。
expression为一个表达式
exception_class为一个指定类
XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, ...)
expression没抛指定类、指定名字的异常,测试失败。
expression为一个表达式
exception_class为一个指定类
exception_name为一个指定名字
XCTAssertNoThrow(expression, ...)
expression抛出异常时,测试失败。
expression为一个表达式
XCTAssertNoThrowSpecific(expression, exception_class, ...)
expression抛出指定类的异常,测试失败。
expression为一个表达式
XCTAssertNoThrowSpecificNamed(expression, exception_class, exception_name, ...)
expression抛出指定类、指定名字的异常,测试失败。
expression为一个表达式
exception_class为一个指定类
exception_name为一个指定名字
参考资料:
https://www.cnblogs.com/shunyang/p/8681111.html
https://www.cnblogs.com/aston/p/7259825.html
https://www.cnblogs.com/dyh2025/p/9251144.html