SpringBoot中单元测试的使用

这篇具有很好参考价值的文章主要介绍了SpringBoot中单元测试的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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 

问题解决

我的是因为之前的一个配置文件没有修改所以才出现的问题,我看网上的解决方法有下面的几种

  1. spring-test坐标的版本较低,按我上面的pom坐标这么改便可以解决问题(这个是我第一次报错的时候改的),参考博文
  2. 在@SpringBootTest这个注解上面增加一个参数,如下所示:参考博客,Web项目
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 作用是启动Spring的ApplicationContext,参数webEnvironment指定了运行的web环境

注解

注解与 Junit4 是一致的
SpringBoot中单元测试的使用
更多的配置说明可以看:这篇博客

@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

其包含的属性如下:

  1. value 指定配置属性
  2. properties 指定配置属性,和value意义相同
  3. classes 指定配置类,等同于@ContextConfiguration中的class,若没有显示指定,将查找嵌套的@Configuration类,然后返回到SpringBootConfiguration搜索配置
  4. 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() {
            returnTestConfiguration;
        }
    }

    @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 对象是否有被正确的顺序调用,以及按照期望的参数被调用

SpringBoot中单元测试的使用

与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章节

assertThat 基本语法
参考这篇博客文章来源地址https://www.toymoban.com/news/detail-483066.html

assertThat( [value], [matcher statement] );
  1. value 是接下来想要测试的变量值;
  2. matcher statement 是使用 Hamcrest 匹配符来表达的对前面变量所期望的值的声明,如果 value 值与 matcher statement 所表达的期望值相符,则测试成功,否则测试失败。

到了这里,关于SpringBoot中单元测试的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Springboot 如何使用Powermock做单元测试

    一、为什么要使用Mock工具 在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,远程服务, 文件系统等等)。 而我们没法控制这些外部依赖的对象,为了解决这个问题,我们就需要用到Mock工具来模拟这些外部依赖的

    2024年02月14日
    浏览(42)
  • vue 引入jest 单元测试

    为什么要搞单元测试,好处有什么。 提测需要, 代码覆盖率达到95%,分支覆盖率达到100% ,不达到要求,不给测。 确保代码正确性。单元测试可以检测和发现代码中的错误,在开发期间及时纠正。 提高代码质量。进行单元测试可以思考更多场景,添加边界测试用例,找到更

    2024年01月18日
    浏览(46)
  • Eclipse中引入JUnit进行单元测试

    1.  在eclipse中添加junit.jar包 打开eclipse-菜单栏点击project-properties-Java Build Path-Libraries-Modulepath-Add External JARS-找到自己下载的junit.jar点击打开,即完成。 2. 在左侧的项目浏览器目录中就可以看到一个JUnit4的目录就引入进来了,如下图所示: 3. 我们新建一个测试类,在其中添加一

    2024年02月11日
    浏览(34)
  • SpringBoot单元测试--Mockito+Junit5框架使用

    作为程序员为了提前发现代码bug,优化代码; 通常我们写完某个功能模块代码后都需要写单元测试对代码块进行测试(特别是敏捷开发中);Java项目最常用的单元测试框架即为Junit(目前最新版本为Junit5),SpringBoot本身也整合了该框架。在写单元测试时代码块中的调到第三方接口方

    2024年02月02日
    浏览(47)
  • [Springboot 单元测试笔记] - Mock 和 spy的使用

    通常单元测试中,我们会隔离依赖对于测试类的影响,也就是假设所有依赖的一定会输出理想结果,在测试中可以通过Mock方法来确保输出结果,这也就引入另一个测试框架Mockito。 Mockito框架的作用就是模拟接口功能,并不运行模拟接口的实际逻辑,而是直接输出一个假定结果

    2024年02月13日
    浏览(36)
  • Springboot 使用插件 自动生成Mock单元测试 Squaretest

    很多公司对分支单测覆盖率会有一定的要求,比如 单测覆盖率要达到 60% 或者 80%才可以发布。 有时候工期相对紧张,就优先开发功能,测试功能,然后再去补单元测试。 但是编写单元测试又比较浪费时间,有没有能够很大程度上自动化生成单元测试的插件,自己改下就行

    2023年04月08日
    浏览(51)
  • idea中添加单元测试@Test注解引入

    添加依赖,使用 @Test 即可。 @Test注解找不到或没有的原因: 我们要进行项目的某部分的test测试,会放在名为test的文件夹下,而现在我们的文件夹测试并不是test下面的一个测试,所以如果我们希望在别的地方也可以利用test注解,只需要去掉scope这一行就行了。

    2024年02月22日
    浏览(43)
  • 为什么需要单元测试?

    为什么需要单元测试? 从产品角度而言,常规的功能测试、系统测试都是站在产品局部或全局功能进行测试,能够很好地与用户的需要相结合,但是缺乏了对产品研发细节(特别是代码细节的理解)。 从测试人员角度而言,功能测试和系统测试以及其他性能测试等等对测试

    2024年02月12日
    浏览(69)
  • 硬件单元电路测试需要写哪些内容

    在测试一个单元电路或者硬件功能,需要提前书写测试计划或测试用例,一个小的测试用例该包含哪些内容? 在单元电路或硬件功能测试时,某个项目的测试目标是什么?我个人是这样定义的,能不能测出问题,测出问题时能不能优化改进,需要在测试目标里明确。 比如说

    2024年02月15日
    浏览(45)
  • 后端学习2.1:引入Junit,对接口做单元测试

    本文将对在Springboot中如何使用Junit进行单元测试进行简单示例和介绍,项目的完整目录层次如下图所示: (在和main文件夹同级的文件中有一个test文件,在其中添加对应的测试类,一般以testXXXX或XXXXTest命名) 操作步骤: 在Springboot中可以通过TestRestTemplate对Controller进行测试; 目

    2024年02月06日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包