1、测试
在开发阶段的时候最重要的是单元测试了,springboot对单元测试的支持已经很完善了。
1、在pom包中添加spring-boot-starter-test包引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、开发测试类
@RunWith是JUnit的一个注解, 用来告诉JUnit不要使用内置的方式进行单元测试, 而应该使用指定的类做单元测试,对于Spring单元测试总是要使用 SpringRunner.class,如果我们使用的是JUnit 4 那么需要添加
@RunWith(SpringRunner.class)
否则所有注解将会被忽略如果你使用的是JUnit5 ,那么在
SpringBootTest
上没有必要添加@ExtendWith
,因为@…Test
已经添加了ExtendWith
@SpringBootTest用来指定SpringBoot应用程序的入口类, 该注解默认会根据包名逐级往上找, 一直找到一个SpringBoot主程序class为止, 然后启动该类为单元测试准备Spring上下文环境. Spring单元测试并不在每个测试方法前都移动一个全新的Spring上下文, 因为这样做太耗费时间, 而是会缓存上下文环境. 如果某个测试方法需要重新准备Spring上下文, 需要在该方法上加@DirtiesContext 注解.
主程序java程序必须是SpringBootApplication程序, 否则测试用例会报如下错误:
Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test java.lang.IllegalStateException.
以最简单的helloworld为例,在测试类的类头部需要添加:@RunWith(SpringRunner.class)
和@SpringBootTest
注解,在测试方法的顶端添加@Test
即可,最后在方法上点击右键run就可以运行。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootdemoApplicationTests {
@Test
public void hello(){
System.out.println("hello");
}
}
Controller单元测试(未)
Service单元测试(未)
新断言assertThat使用(未)
什么时候用断言(未)?
实际使用中,可以按照项目的正常使用去注入dao层代码或者是service层代码进行测试验证,spring-boot-starter-test提供很多基础用法,更难得的是增加了对Controller层测试的支持。
//简单验证结果集是否正确
Assert.assertEquals(3, userMapper.getAll().size());
//验证结果集,提示
Assert.assertTrue("错误,正确的返回值为200", status == 200);
Assert.assertFalse("错误,正确的返回值为200", status != 200);
引入了MockMvc
支持了对Controller层的测试,简单示例如下:
public class HelloControlerTests {
private MockMvc mvc;
//初始化执行
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
}
//验证controller是否正常响应并打印返回结果
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
//验证controller是否正常响应并判断返回结果是否正确
@Test
public void testHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Hello World")));
}
}
单元测试是验证你代码第一道屏障,要养成每写一部分代码就进行单元测试的习惯,不要等到全部集成后再进行测试,集成后因为更关注整体运行效果,很容易遗漏掉代码底层的bug.
单元测试回滚
单元个测试的时候如果不想造成垃圾数据,可以开启事物功能,记在方法或者类头部添加@Transactional
注解即可
@Test
@Transactional
public void add(){
LearnResource bean = new LearnResource();
bean.setAuthor("测试回滚");
bean.setTitle("回滚用例");
bean.setUrl("http://tengj.top");
learnService.save(bean);
}
这样测试完数据就会回滚了,不会造成垃圾数据。如果你想关闭回滚,只要加上@Rollback(false)
注解即可。@Rollback
表示事务执行完回滚,支持传入一个参数value,默认true即回滚,false不回滚。
如果你使用的数据库是Mysql,有时候会发现加了注解@Transactional
也不会回滚,那么你就要查看一下你的默认引擎是不是InnoDB,如果不是就要改成InnoDB
2、打成jar包
如果你使用的是maven来管理项目,执行以下命令既可以
-
cd 项目跟目录(和pom.xml同级)
-
mvn clean package
-
## 或者执行下面的命令
-
## 排除测试代码后进行打包
-
mvn clean package -Dmaven.test.skip=true
打包完成后jar包会生成到target目录下,命名一般是 项目名+版本号.jar
启动jar包命令
java -jar springbootdemo-1.0.0-SNAPSHOT.jar
这种方式,只要控制台关闭,服务就不能访问了。下面我们使用在后台运行的方式来启动:
nohup java -jar springbootdemo-1.0.0-SNAPSHOT.jar &
也可以在启动的时候选择读取不同的配置文件
java -jar springbootdemo-1.0.0-SNAPSHOT.jar --spring.profiles.active=dev
也可以在启动的时候设置jvm参数
java -Xms10m -Xmx80m -jar springbootdemo-1.0.0-SNAPSHOT.jar &
gradle
如果使用的是gradle,使用下面命令打包
gradle build
java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
3、打成war包
打成war包一般可以分两种方式来实现,第一种可以通过eclipse这种开发工具来导出war包,另外一种是使用命令来完成,这里主要介绍后一种
1、maven项目,修改pom包,将jar改为war
<packaging>war</packaging>
2、打包时排除tomcat.
在这里将scope属性设置为provided,这样在最终形成的WAR中不会包含这个JAR包,因为Tomcat或Jetty等服务器在运行时将会提供相关的API类。
<!-- 自动添加 Tomcat 和 Spring MVC 的依赖 进行自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
3、注册启动类
创建ServletInitializer.java,继承SpringBootServletInitializer ,覆盖configure(),把启动类Application注册进去。外部web应用服务器构建Web Application Context的时候,会把启动类添加进去。
package com.guxilong;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringbootdemoApplication.class);
}
}
最后执行
mvn clean package -Dmaven.test.skip=true
会在target目录下生成:项目名+版本号.war文件,拷贝到tomcat服务器中启动即可。
gradle
如果使用的是gradle,基本步奏一样,build.gradle中添加war的支持,排除spring-boot-starter-tomcat:
...
apply plugin: 'war'
...
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.4.2.RELEASE"){
exclude mymodule:"spring-boot-starter-tomcat"
}
}
...
再使用构建命令
gradle build
war会生成在build\libs 目录下。