springboot测试
@RunWith
@RunWith 翻译成中文就是 测试运行器,JUnit所有的测试方法都是由测试运行器负责执行。
当一个类用@RunWith注释或继承一个用@RunWith注释的类时,JUnit将调用它所引用的类来运行该类中的测试而不是开发者去在junit内部去构建它。
JUnit为单元测试提供了一个默认的测试运行器BlockJUnit4ClassRunner,但是没有限制必须使用默认的运行器。
@RunWith(JUnit4.class)就是指用JUnit4来运行
@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境
@RunWith(SpringRunner.class):SpringRunner是SpringJUnit4ClassRunner的一个别名。
@RunWith(Suite.class)的话就是一套测试集合,
@ContextConfiguration
@ContextConfiguration注解来标注我们想要向测试类导入那些bean,该注解通常和@RunWith注解一起使用。
当一个类添加了注解@Component,那么他就自动变成了一个bean,就不需要再Spring配置文件中显示的配置了。把这些bean收集起来通常有2种方式:Java的方式和XML的方式。当这些bean收集起来之后,当我们想要在某个测试类使用@Autowired注解来引入这些收集起来的bean时,只需要给这个测试类添加@ContextConfiguration注解来标注我们想要导入这个测试类的某些bean。
XML方式
我们先看看老年人使用的XML方式:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd >
<!-- 自动扫描该包 -->
<context:component-scan base-package="com" />
</beans>
这个XML文件通过<context:component-scan base-package=“com” />标签将com包下的bean全都自动扫描进来。
下面我们就可以测试了。
一般这么写:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/*.xml"})
public class CDPlayerTest {
}
@ContextConfiguration括号里的locations = {“classpath*?*.xml”}就表示将class路径里的所有.xml文件都包括进来,那么刚刚创建的那么XML文件就会包括进来,那么里面自动扫描的bean就都可以拿到了,此时就可以在测试类中使用@Autowired注解来获取之前自动扫描包下的所有bean
classpath和classpath*区别:
classpath:只会到你的class路径中查找找文件。
classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。
单个文件
@ContextConfiguration(Locations=“classpath:applicationContext.xml”)
@ContextConfiguration(classes = SimpleConfiguration.class)
多个文件时,可用{}
@ContextConfiguration(locations = { “classpath:spring1.xml”, “classpath:spring2.xml” })
Java方式
如果使用Java的方式就会很简单了,我们就不用写XML那么繁琐的文件了,我们可以创建一个Java类来代替XML文件,只需要在这个类上面加上@Configuration注解,然后再加上@ComponentScan注解就开启了自动扫描,如果注解没有写括号里面的东西,@ComponentScan默认会扫描与配置类相同的包。
@Configuration
@ComponentScan
public class CDPlayConfig {
}
此时如果想要测试的话,就可以这么写:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayConfig.class)
public class CDPlayerTest {
}
SpringBoot测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class Test {
}
@SpringBootTes
这个@SpringBootTest注解意思就是将SpringBoot主类中导入的bean全都包含进来。
此时SpringBoot主类也被当作了bean的收集器。类似上文的CDPlayConfig。
SpringBoot测试步骤
直接在测试类上面加上如下2个注解
@RunWith(SpringRunner.class)
@SpringBootTest
就能取到spring中的容器的实例,如果配置了@Autowired那么就自动将对象注入。
具体测试实例1
在src/main下建立UserService类,对其进行单于测试,生产其单元测试类(使用command+shift+T快捷键),生成的test类在src/test下
@Service
public class UserService {
public Integer addUser(String username){
System.out.println("user dao adduser [username="+username+"]");
if(username == null){
return 0;
}
return 1;
}
}
springboot启动类:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void addUser() throws Exception {
Assert.assertEquals(Integer.valueOf(1),userService.addUser("zhihao.miao"));
Assert.assertEquals(Integer.valueOf(0),userService.addUser(null));
}
}
具体测试实例2
编写启动入口类
@SpringBootApplication
public class StartUpApplication {
public static void main(String[] args) {
SpringApplication.run(StartUpApplication.class, args);
}
}
编写Controller类
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Hello Spring Boot,Index!";
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
return "Spring Boot Test Demo!";
}
}
编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = StartUpApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerTest {
/**
* @LocalServerPort 提供了 @Value("${local.server.port}") 的代替
*/
@LocalServerPort
private int port;
private URL base;
@Autowired
private TestRestTemplate restTemplate;
@Before
public void setUp() throws Exception {
String url = String.format("http://localhost:%d/", port);
System.out.println(String.format("port is : [%d]", port));
this.base = new URL(url);
}
/**
* 向"/test"地址发送请求,并打印返回结果
* @throws Exception
*/
@Test
public void test1() throws Exception {
ResponseEntity<String> response = this.restTemplate.getForEntity(
this.base.toString() + "/test", String.class, "");
System.out.println(String.format("测试结果为:%s", response.getBody()));
}
其中,classes属性指定启动类,SpringBootTest.WebEnvironment.RANDOM_PORT经常和测试类中@LocalServerPort一起在注入属性时使用。会随机生成一个端口号。
在测试环境下获取bean
在src/main下新建一个实例User
@Component
public class User {
}
src/test下创建测试类测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserTest {
@Autowired
public ApplicationContext context;
@Test
public void testNotNull(){
Assert.assertNotNull(context.getBean(User.class));
}
}
只在测试环境有效的bean
在src/test下新建二个类,我们发现分别使用@TestComponent和@TestConfiguration二个注解修饰,这些类只在测试环境生效
@TestComponent
public class Cat {
public void index(){
System.out.println("cat index");
}
}
@TestConfiguration
public class TestBeanConfiguration {
@Bean
public Runnable createRunnable(){
return () -> System.out.println("=====createRunnable=======");
}
}
测试类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {TestBeanConfiguration.class,Cat.class})
public class TestApplication {
@Autowired
public ApplicationContext context;
@Test
public void testNotNull(){
Runnable runnable = context.getBean(Runnable.class);
runnable.run();
System.out.println("--------");
Cat cat = context.getBean(Cat.class);
cat.index();
}
}
需要在@SpringBootTest注解的参数classes中加入参数,表示将某些类纳入测试环境的容器中。