pom文件需要引入的坐标
<!-- test的起步依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
需要使用的注解
import org.elasticsearch.client.RestHighLevelClient;
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;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {YourApplication.class})
public class EsDemoTest {
@Autowired
private XXXXXService xxxxxService;
@Test
public void test(){
System.out.println(xxxxxService.xxx);
}
}
出现的问题
会报错,我是报下面的错误
[o.s.test.context.TestContextManager ]: Caught exception while allowing TestExecutionListener
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
问题解决
我的是因为之前的一个配置文件没有修改所以才出现的问题,我看网上的解决方法有下面的几种
- spring-test坐标的版本较低,按我上面的pom坐标这么改便可以解决问题(这个是我第一次报错的时候改的),参考博文
- 在@SpringBootTest这个注解上面增加一个参数,如下所示:参考博客,Web项目
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 作用是启动Spring的ApplicationContext,参数webEnvironment指定了运行的web环境@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
注解
注解与 Junit4 是一致的
更多的配置说明可以看:这篇博客
@RunWith(SpringRunner.class)
是JUnit的注解,作用是关联Spring Boot Test,使运行JUnit时同时启动Spring,该注解能够让Junit运行在Spring测试环境中,得到Spring上下文支持4.3版本中提供了等同于SpringJUnit4ClassRunner.class的简写类SpringRunner.class
@SpringBootTest
当测试中需要使用Spring Boot功能时,可以使用@SpringBootTest
注解,装配Spring上下文。
@SpringBootTest注解意思就是将SpringBoot主类中导入的bean全都包含进来。
当作为普通Spring单元测试时,可以使用@ContextConfiguration
,装配Spring 上下文。
如果指定的classes为普通Configer(@SpringBootConfiguration)配置类,则会以此配置初始化Spring 上下文,而不会加载其他Bean到Spring容器
如果未指定classes 参数或者指定的classes参数不是启动main函数入口
@SpringBootTest(classes = {YourApplication.class})(也就是使用@SpringBootApplication注解的类),则会自动从当前测试类包一层一层向上检索,直到找到有@SpringBootApplication或@SpringBootConfiguration注释的类为止
。以此来启动Spring Boot应用,并装载Spring上下文。
如果未检索到Spring Boot启动主配置类,则会抛出异常: java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=…) with your test
其包含的属性如下:
- value 指定配置属性
- properties 指定配置属性,和value意义相同
- classes 指定配置类,等同于@ContextConfiguration中的class,若没有显示指定,将查找嵌套的@Configuration类,然后返回到SpringBootConfiguration搜索配置
- webEnvironment 指定web环境,可选值有:MOCK、RANDOM_PORT、DEFINED_PORT、NONE
- MOCK 此值为默认值,该类型提供一个mock环境,此时内嵌的服务(servlet容器)并没有真正启动,也不会监听web端口。
- RANDOM_PORT 启动一个真实的web服务,监听一个随机端口。
- DEFINED_PORT 启动一个真实的web服务,监听一个定义好的端口(从配置中读取)。
- NONE 启动一个非web的ApplicationContext,既不提供mock环境,也不提供真是的web服务。
集成测试侧重于集成应用程序的不同层,意味着不涉及Mock
@ContextConfiguration
@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
4.3版本中提供了等同于SpringJUnit4ClassRunner.class的简写类SpringRunner.class
当作为普通Spring单元测试时,可以使用@ContextConfiguration
,装配Spring 上下文。
当一个类添加了注解@Component,那么他就自动变成了一个bean
当这些bean收集起来之后,当我们想要在某个测试类使用@Autowired注解来引入这些收集起来的bean时,只需要给这个测试类添加@ContextConfiguration注解来标注我们想要导入这个测试类的某些bean
使用
@Component
public class CDPlayConfig {
}
进行测试,这个只会将这个Config注入的ben获取到
@RunWith(SpringRunner.class)
@ContextConfiguration(classes=CDPlayConfig.class)
public class CDPlayerTest {
@Autowired
private CDPlayConfig Config;
@Test
public void test(){
congiog.xxx;
}
}
多bean导入
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {A.class, B.class})
public class CDPlayerTest {
}
如果默认不写的话,可以根据测试的类名,去找到与之对应的配置文件。
可以查看这篇博客
@TestConfiguration
通过@TestConfiguration创建的Bean,作用范围在test里,不会影响到正式环境。通过@Autowired可以拿到创建的bean:
这一篇参考的博文代码有一点问题,下面的是我自己本地测试过的,没有写得大奖还是谨慎参考吧,这个博客后面的那些测试方法测试过,发现行不通,可能是pom坐标问题吧
@TestConfiguration作为内部类
通过@TestConfiguration创建的Bean,作用范围在test里,不会影响到正式环境。通过@Autowired可以拿到创建的bean:只能是同一个类里面,如果在其他类里面进行测试,使用@Autowired注入后,是会报错端的,需要不报错需要使用@Import把配置类导入进来,或者也可使用@SpringBootTest(classes = CourseConfig.class)导入配置类
@SpringBootTest
public class CourseInnerClassTest {
@TestConfiguration
static class CourseConfig {
//这里需要使用static,不使用的话是会报错的
@Bean
public static String course() {
return “TestConfiguration”;
}
}
@Autowired
private Course course;
@Test
public void test() {
//断言,判断返回的值是否正确,正确的话是不会有如何报错的,对比content的内容和"TestConfiguration"是否一致,不一致的话会报错
Assert.assertEquals(“TestConfiguration”, course);
}
}
@TestConfiguration作为独立的配置类
@TestConfiguration
public class CourseConfig {
@Bean
public String course2() {
return "TestConfiguration";
}
}
在测试时,需要使用@Import把配置类导入进来,或者也可使用@SpringBootTest(classes = CourseConfig.class)导入配置类
@SpringBootTest
@Import(CourseConfig.class)
public class CourseSeparateClassTest {
@Autowired
private Course course2;
@Test
public void test() {
Assert.assertEquals("TestConfiguration", CourseConfig.course2);
}
}
@WebAppConfiguration
若你在一个测试类上加了@ContextConfiguration注解,则表示告诉Spring该集成测试加载的ApplicationContext应该是WebApplicationContext,表明这是一个WEB应用配置
作用是模拟ServletContext。注解在类上,用来声明加载的ApplicationContex 是一个WebApplicationContext ,它的属性指定的是Web资源的位置,默认为 src/main/webapp ,自定义修改为 resource
是一个用于声明集成测试所加载的ApplicationContext须是WebApplicationContext的类级别的注解
测试
超时测试
@Test(timeout = 1000)
public void testTimeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
System.out.println("Complete");
}
上面测试会失败,在一秒后会抛出异常org.junit.runners.model.TestTimeOutException:test timedout after 1000 millseconds
异常测试
可以测试代码是否它抛出想要得到的异常。expected参数和@Test 注释一起使用。现在让我们看看活动中的@Test(expected)
@Test(expected)
public void testTimeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
System.out.println("Complete");
}
mock
参考博文
参考博客2
参考博文3
在面向对象的程序设计中,模拟对象(mock object)是以可控的方式模拟真实对象行为的假对象。在编程过程中,通常通过模拟一些输入数据,来验证程序是否达到预期结果。
使用模拟对象,可以模拟复杂的、真实的对象行为。如果在单元测试中无法使用真实对象,可采用模拟对象进行替代。
使用Mockito一般分为三个步骤:
1.模拟测试类所需的外部依赖
2.执行测试代码
3.判断执行结果是否达到预期
Mockito 是一种 Java Mock 框架,主要是用来做 Mock 测试,它可以模拟任何 Spring 管理的 Bean、模拟方法的返回值、模拟抛出异常等等,避免你为了测试一个方法,却要自行构建整个 bean 的依赖链。
同时也会记录调用这些模拟方法的参数、调用顺序,从而可以校验出这个 Mock 对象是否有被正确的顺序调用,以及按照期望的参数被调用。
与Mockito使用–@MockBean
使用@MockBean注解来生成一个mock的bean,我们可以使用Mockito.when来模拟一些方法(比如Mock Jpa的Repository的find方法,这样就算数据库里的数据还没有准备好,我们也可以自己模拟数据)
参考博文
使用
Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 )
@SpringBootTest
public class CourseServiceTest {
@MockBean
private CourseService courseService;
@Test
public void test() {
Mockito.when( 对象.方法名() ).thenReturn(自定义结果);
Assert.assertEquals(自定义结果, 对象.方法名());
}
}
Service单元测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {YourApplication.class})
public class EsDemoTest {
@Autowired
private XXXXXService xxxxxService;
@Test
public void test(){
System.out.println(xxxxxService.xxx);
}
}
Controller单元测试
参考博客
有时候需要对Controller层(API)做测试,这时候就得用到MockMvc,不必启动工程就能测试这些接口。
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便
测试方法1:步骤
在boot项目中写一个controller接口,如下:
@RestController
public class HelloController {
@RequestMapping("/testMock")
public String hello(String name){
return "hello "+name;
}
}
写测试方法,如下:
import org.junit.Assert;
import org.junit.Before;
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.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
//SpringBoot1.4版本之前用的是SpringJUnit4ClassRunner.class
@RunWith(SpringRunner.class)
//SpringBoot1.4版本之前用的是@SpringApplicationConfiguration(classes = Application.class)
@SpringBootTest(classes = App.class)
//测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的
@WebAppConfiguration
public class HelloControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp(){
//MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,将会从该上下文获取相应的控制器并得到相应的MockMvc;
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
}
@Test
public void getHello() throws Exception{
/**
* 1、mockMvc.perform执行一个请求,Post请求就用.post方法
* 2、MockMvcRequestBuilders.get("XXX")构造一个请求,Post请求就用.post方法
* 3、ResultActions.param添加请求传值
* 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
accept(MediaType.APPLICATION_JSON_UTF8)代表客户端希望接受的数据类型为application/json;charset=UTF-8
contentType(MediaType.APPLICATION_JSON_UTF8)代表发送端发送的数据格式是application/json;charset=UTF-8
* 5、ResultActions.andExpect添加执行完成后的断言。
* 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
* 5、ResultActions.andReturn表示执行完成后,返回响应的结果。
比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息
*/
MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/testMock")
.param("name","testmock")
.accept(MediaType.TEXT_HTML_VALUE)
//.contentType(MediaType.APPLICATION_JSON_UTF8)
)
//等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.status().isOk())
//等同于 Assert.assertEquals("hello testmock",content);
// .andExpect(MockMvcResultMatchers.content().string("hello testmock"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
int status=mvcResult.getResponse().getStatus(); //得到返回代码
String content=mvcResult.getResponse().getContentAsString(); //得到返回结果
//断言,判断返回代码是否正确
Assert.assertEquals(200,status);
//断言,判断返回的值是否正确,对比content的内容和"hello ddd"是否一致,不一致的话会报错
Assert.assertEquals("hello ddd",content);
}
}
然后直接测试即可
补充
MockMvcBuilders提供了对应的创建方法standaloneSetup 方法和webAppContextSetup方法,在使用时直接调用即可
private MockMvc mockMvc;
@Autowire
private WebApplicationContext webApplicationContext;
@Before
public void setup() {
/*实例化方式一*/
mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
/*实例化方式二*/
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
更多的测试可以看这个博客的Mockito章节文章来源:https://www.toymoban.com/news/detail-483066.html
assertThat 基本语法
参考这篇博客文章来源地址https://www.toymoban.com/news/detail-483066.html
assertThat( [value], [matcher statement] );
- value 是接下来想要测试的变量值;
- matcher statement 是使用 Hamcrest 匹配符来表达的对前面变量所期望的值的声明,如果 value 值与 matcher statement 所表达的期望值相符,则测试成功,否则测试失败。
到了这里,关于SpringBoot中单元测试的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!