赞
踩
记录一下我总结的SpringBoot单元测试的方法。
首先贴一下用到的代码:
1、目录结构
2、pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.java.ccs</groupId> <artifactId>springboottest</artifactId> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> <spring.version>5.2.0.RELEASE</spring.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> </parent> <dependencies> <!-- 先声明jmockit的依赖--> <dependency> <groupId>org.jmockit</groupId> <artifactId>jmockit</artifactId> <version>1.36</version> <scope>test</scope> </dependency> <!-- 再声明junit的依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--Spring核心容器模块--> <!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-core</artifactId>--> <!--<version>${spring.version}</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-beans</artifactId>--> <!--<version>${spring.version}</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring-context</artifactId>--> <!--<version>${spring.version}</version>--> <!--</dependency>--> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3、applicationContext.xml文件
这里其实就是Spring配置文件,模拟通过配置文件实现依赖注入的形式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启annotation配置 -->
<context:annotation-config/>
<!-- 扫描以com开头的包里边的bean -->
<context:component-scan base-package="com.java.ccs.springboottest"/>
</beans>
4、SpringBoot的启动类
/**
* @author Caocs
* @date 2020/4/13
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
5、dao层
import org.springframework.stereotype.Component;
/**
* @author Caocs
* @date 2020/4/13
*/
@Component
public class UserDao {
public String getUser(String name){
return "this is "+ name;
}
}
6、service层
import com.java.ccs.springboottest.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author Caocs * @date 2020/4/13 */ @Service public class UserService { @Autowired UserDao userDao; public String getUser(String name){ return userDao.getUser(name); } }
7、controller层
import com.java.ccs.springboottest.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author Caocs * @date 2020/4/13 */ @Service public class UserAction { @Autowired UserService userService; public void getUser(){ String name = "ccs"; // 依赖注入时,如果通过new UserService()生成新实例的话,则userService 对象中useDao对象就会没有注入进来,会为null。 // UserService userService = new UserService(); String result = userService.getUser(name); System.out.println(result); } }
对SpringBoot进行单元测试,我总结了下面几种方式:
使用ApplicationContext来初始化系统,然后获取实例。
import com.java.ccs.springboottest.action.UserAction; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author Caocs * @date 2020/4/13 */ public class UserTest { @Test public void test(){ // 使用ApplicationContext来初始化系统 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //通过spring获取实例对象 UserAction userAction = (UserAction) context.getBean("userAction"); userAction.getUser(); } }
以SpringJUnit4ClassRunner作为启动类,并指定配置文件
import com.java.ccs.springboottest.action.UserAction; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Caocs * @date 2020/4/13 */ //RunWith的value属性指定以spring test的SpringJUnit4ClassRunner作为启动类 //如果不指定启动类,默认启用的junit中的默认启动类 @RunWith(value = SpringJUnit4ClassRunner.class) //指定在单元测试启动的时候创建spring的工厂类对象 @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class UserTest2 { @Autowired UserAction userAction; @Test public void test(){ userAction.getUser(); } }
通过@SpringBootTest指定启动项,加载初始化。然后用SpringRunner类启动
import com.java.ccs.springboottest.action.UserAction; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; /** * @author Caocs * @date 2020/4/13 */ // SpringRunner其实就是继承自SpringJUnit4ClassRunner类 @RunWith(SpringRunner.class) // 启动Spring,指定启动类 @SpringBootTest(classes = App.class) public class UserTest3 { @Autowired UserAction userAction; @Test public void test(){ userAction.getUser(); } }
通过@SpringBootTest指定启动项,加载初始化。然后用SpringRunner类启动。
使用JMockit
中的MockUp
方式对方法进行Mock。
import com.java.ccs.springboottest.action.UserAction; import com.java.ccs.springboottest.service.UserService; import mockit.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /** * @author Caocs * @date 2020/4/13 */ // SpringRunner其实就是继承自SpringJUnit4ClassRunner类 @RunWith(SpringRunner.class) // 启动Spring,指定启动类 @SpringBootTest(classes = App.class) public class UserTest4 { @Autowired UserAction userAction; @Test public void test(){ //进行mock new MockUp<UserService>(){ @Mock public String getUser(String name){ return "userService mock result"; } }; userAction.getUser(); } }
通过@SpringBootTest指定启动项,加载初始化。然后用SpringRunner类启动。
使用JMockit
中的Expectations
方式对方法进行Mock。
import com.java.ccs.springboottest.action.UserAction; import com.java.ccs.springboottest.service.UserService; import mockit.Expectations; import mockit.Mock; import mockit.MockUp; import mockit.Mocked; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /** * @author Caocs * @date 2020/4/13 */ // SpringRunner其实就是继承自SpringJUnit4ClassRunner类 @RunWith(SpringRunner.class) // 启动Spring,指定启动类 @SpringBootTest(classes = App.class) public class UserTest5 { @Autowired UserAction userAction; @Test public void test(@Mocked UserService userService){ new Expectations(UserService.class){ // new Expectations(userService){ // 此处不能传对象作为参数,因为@Mocked的对象和userAction中注入的对象不是同一个对象 { userService.getUser("ccs"); result = "userService mock result"; } }; userAction.getUser(); } }
使用TestWatcher
对单元测试结果展示进行包裹,便于展示。
并且自定义抽象类
来启动@SpringBootTest单元测试。
这样,以后就可以直接继承这个抽象类进行SpringBoot的单元测试。
1、TestProgress 类
通过继承TestWatcher
,用于实现对单元测试结果进行包裹。
import org.junit.rules.TestWatcher; import org.junit.runner.Description; import java.time.Duration; import java.time.Instant; /** * @author Caocs * @date 2020/4/19 */ public class TestProgress extends TestWatcher { public static final String ANSI_RESET = "\u001B[0m"; public static final String ANSI_GREEN = "\u001B[32m"; private Instant start; @Override protected void starting(Description description) { start = Instant.now(); System.out.println("\n" + ANSI_GREEN + "***************[Test Case starting] " + description.getTestClass().getSimpleName() + "." + description.getMethodName() + "()***************\n" + ANSI_RESET); } @Override protected void finished(Description description) { System.out.println("\n" + ANSI_GREEN + "***************[Test Case finished] " + description.getTestClass().getSimpleName() + "." + description.getMethodName() + "()***************\n" + ANSI_RESET); System.out.println(String.format("end run caculate,cost{%d}(ms)", Duration.between(start, Instant.now()).toMillis())); } }
2、SpringBootTestInitializer类
其实只是一个单纯的SpringBoot启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; /** * @author Caocs * @date 2020/4/19 */ @SpringBootApplication(scanBasePackages = {"com.java.ccs.springboottest"}) public class SpringBootTestInitializer extends SpringBootServletInitializer { // 此处不用继承自SpringBootServletInitializer也可以 public static void main(String[] args) { SpringApplication.run(SpringBootTestInitializer.class, args); } /** * Configure your application when it’s launched by the servlet container */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootTestInitializer.class); } }
3、AbstractSpringContextTest类
把@SpringBootTest做单元测试的部分,做成一个抽象类。这样,以后写单元测试的时候只需要继承该类即可。
import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Caocs * @date 2020/4/19 */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = SpringBootTestInitializer.class) public abstract class AbstractSpringContextTest { @Rule public TestRule testProgress = new TestProgress(); }
4、测试用例类
import com.java.ccs.springboottest.action.UserAction; import com.java.ccs.springboottest.service.UserService; import mockit.Mock; import mockit.MockUp; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; /** * @author Caocs * @date 2020/4/19 */ public class UserTest6 extends AbstractSpringContextTest { @Autowired UserAction userAction; @Test public void test(){ //进行mock new MockUp<UserService>(){ @Mock public String getUser(String name){ return "userService mock result"; } }; userAction.getUser(); } }
5、结果显示
这样,我们在控制台上,会发现我们的测试结果外边做了封装,更加的直观明了。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。