详解Spring Boot Junit单元测试

Junit这种老技术,现在又拿出来说,不为别的,某种程度上来说,更是为了要说明它在项目中的重要性。

凭本人的感觉和经验来说,在项目中完全按标准都写Junit用例覆盖大部分业务代码的,应该不会超过一半。

刚好前段时间写了一些关于SpringBoot的帖子,正好现在把Junit再拿出来从几个方面再说一下,也算是给一些新手参考了。

那么先简单说一下为什么要写测试用例

1. 可以避免测试点的遗漏,为了更好的进行测试,可以提高测试效率

2. 可以自动测试,可以在项目打包前进行测试校验

3. 可以及时发现因为修改代码导致新的问题的出现,并及时解决

那么本文从以下几点来说明怎么使用Junit,Junit4比3要方便很多,细节大家可以自己了解下,主要就是版本4中对方法命名格式不再有要求,不再需要继承TestCase,一切都基于注解实现。

1、SpringBoot Web项目中中如何使用Junit

创建一个普通的Java类,在Junit4中不再需要继承TestCase类了。

因为我们是Web项目,所以在创建的Java类中添加注解:

@RunWith(SpringJUnit4ClassRunner.class) // SpringJUnit支持,由此引入Spring-Test框架支持!
@SpringApplicationConfiguration(classes = SpringBootSampleApplication.class) // 指定我们SpringBoot工程的Application启动类
@WebAppConfiguration // 由于是Web项目,Junit需要模拟ServletContext,因此我们需要给我们的测试类加上@WebAppConfiguration。

接下来就可以编写测试方法了,测试方法使用@Test注解标注即可。

在该类中我们可以像平常开发一样,直接@Autowired来注入我们要测试的类实例。

下面是完整代码:

package org.springboot.sample;

import static org.junit.Assert.assertArrayEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springboot.sample.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

/**
 *
 * @author  单红宇(365384722)
 * @create  2016年2月23日
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootSampleApplication.class)
@WebAppConfiguration
public class StudentTest {

  @Autowired
  private StudentService studentService;

  @Test
  public void likeName() {
    assertArrayEquals(
        new Object[]{
            studentService.likeName("小明2").size() > 0,
            studentService.likeName("坏").size() > 0,
            studentService.likeName("莉莉").size() > 0
          },
        new Object[]{
            true,
            false,
            true
          }
    );
//   assertTrue(studentService.likeName("小明2").size() > 0);
  }

}

接下来,你需要新增无数个测试类,编写无数个测试方法来保障我们开发完的程序的有效性。

2、Junit基本注解介绍

//在所有测试方法前执行一次,一般在其中写上整体初始化的代码
@BeforeClass

//在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码
@AfterClass

//在每个测试方法前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)
@Before

//在每个测试方法后执行,在方法执行完成后要做的事情
@After

// 测试方法执行超过1000毫秒后算超时,测试将失败
@Test(timeout = 1000)

// 测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败
@Test(expected = Exception.class)

// 执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类
@Ignore(“not ready yet”)
@Test

@RunWith

在JUnit中有很多个Runner,他们负责调用你的测试代码,每一个Runner都有各自的特殊功能,你要根据需要选择不同的Runner来运行你的测试代码。

如果我们只是简单的做普通Java测试,不涉及spring Web项目,你可以省略@RunWith注解,这样系统会自动使用默认Runner来运行你的代码。

3、参数化测试

Junit为我们提供的参数化测试需要使用 @RunWith(Parameterized.class)

然而因为Junit 使用@RunWith指定一个Runner,在我们更多情况下需要使用@RunWith(SpringJUnit4ClassRunner.class)来测试我们的Spring工程方法,所以我们使用assertArrayEquals 来对方法进行多种可能性测试便可。

下面是关于参数化测试的一个简单例子:

package org.springboot.sample;

import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ParameterTest {

  private String name;
  private boolean result;

  /**
   * 该构造方法的参数与下面@Parameters注解的方法中的Object数组中值的顺序对应
   * @param name
   * @param result
   */
  public ParameterTest(String name, boolean result) {
    super();
    this.name = name;
    this.result = result;
  }

  @Test
  public void test() {
    assertTrue(name.contains("小") == result);
  }

  /**
   * 该方法返回Collection
   *
   * @return
   * @author SHANHY
   * @create 2016年2月26日
   */
  @Parameters
  public static Collection<?> data(){
    // Object 数组中值的顺序注意要和上面的构造方法ParameterTest的参数对应
    return Arrays.asList(new Object[][]{
      {"小明2", true},
      {"坏", false},
      {"莉莉", false},
    });
  }
}

4、打包测试

正常情况下我们写了5个测试类,我们需要一个一个执行。

打包测试,就是新增一个类,然后将我们写好的其他测试类配置在一起,然后直接运行这个类就达到同时运行其他几个测试的目的。

代码如下:

@RunWith(Suite.class)
@SuiteClasses({ATest.class, BTest.class, CTest.class})
public class ABCSuite {
  // 类中不需要编写代码
} 

5、使用Junit测试HTTP的API接口

我们可以直接使用这个来测试我们的Rest API,如果内部单元测试要求不是很严格,我们保证对外的API进行完全测试即可,因为API会调用内部的很多方法,姑且把它当做是整合测试吧。

下面是一个简单的例子:

package org.springboot.sample;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 *
 * @author  单红宇(365384722)
 * @create  2016年2月23日
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootSampleApplication.class)
//@WebAppConfiguration // 使用@WebIntegrationTest注解需要将@WebAppConfiguration注释掉
@WebIntegrationTest("server.port:0")// 使用0表示端口号随机,也可以具体指定如8888这样的固定端口
public class HelloControllerTest {

  private String dateReg;
  private Pattern pattern;
  private RestTemplate template = new TestRestTemplate();
  @Value("${local.server.port}")// 注入端口号
  private int port;

  @Test
  public void test3(){
    String url = "http://localhost:"+port+"/myspringboot/hello/info";
    MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
    map.add("name", "Tom");
    map.add("name1", "Lily");
    String result = template.postForObject(url, map, String.class);
    System.out.println(result);
    assertNotNull(result);
    assertThat(result, Matchers.containsString("Tom"));
  }

}

6、捕获输出

使用 OutputCapture 来捕获指定方法开始执行以后的所有输出,包括System.out输出和Log日志。

OutputCapture 需要使用@Rule注解,并且实例化的对象需要使用public修饰,如下代码:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootSampleApplication.class)
//@WebAppConfiguration // 使用@WebIntegrationTest注解需要将@WebAppConfiguration注释掉
@WebIntegrationTest("server.port:0")// 使用0表示端口号随机,也可以具体指定如8888这样的固定端口
public class HelloControllerTest {

  @Value("${local.server.port}")// 注入端口号
  private int port;

  private static final Logger logger = LoggerFactory.getLogger(StudentController.class);

  @Rule
  // 这里注意,使用@Rule注解必须要用public
  public OutputCapture capture = new OutputCapture();

  @Test
  public void test4(){
    System.out.println("HelloWorld");
    logger.info("logo日志也会被capture捕获测试输出");
    assertThat(capture.toString(), Matchers.containsString("World"));
  }
}

关于Assert类中的一些断言方法,都很简单,本文不再赘述。

但是在新版的Junit中,assertEquals 方法已经被废弃,它建议我们使用assertArrayEquals,旨在让我们测试一个方法的时候多传几种参数进行多种可能性测试。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Spring Boot实战之单元测试

    本文介绍使用Spring测试框架提供的MockMvc对象,对Restful API进行单元测试 Spring测试框架提供MockMvc对象,可以在不需要客户端-服务端请求的情况下进行MVC测试,完全在服务端这边就可以执行Controller的请求,跟启动了测试服务器一样. 测试开始之前需要建立测试环境,setup方法被@Before修饰.通过MockMvcBuilders工具,使用WebApplicationContext对象作为参数,创建一个MockMvc对象. MockMvc对象提供一组工具

  • 详解SpringBoot之添加单元测试

    本文介绍了详解SpringBoot之添加单元测试,分享给大家,希望此文章对各位有所帮助 在SpringBoot里添加单元测试是非常简单的一件事,我们只需要添加SpringBoot单元测试的依赖jar,然后再添加两个注解就可搞定了. 首先我们来添加单元测试所需要的jar <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test<

  • 详解Spring Boot Junit单元测试

    Junit这种老技术,现在又拿出来说,不为别的,某种程度上来说,更是为了要说明它在项目中的重要性. 凭本人的感觉和经验来说,在项目中完全按标准都写Junit用例覆盖大部分业务代码的,应该不会超过一半. 刚好前段时间写了一些关于SpringBoot的帖子,正好现在把Junit再拿出来从几个方面再说一下,也算是给一些新手参考了. 那么先简单说一下为什么要写测试用例 1. 可以避免测试点的遗漏,为了更好的进行测试,可以提高测试效率 2. 可以自动测试,可以在项目打包前进行测试校验 3. 可以及时发现因

  • 详解Spring Boot中使用Flyway来管理数据库版本

    如果没有读过上面内容的读者,有兴趣的可以一阅.在上面的使用JdbcTemplate一文中,主要通过spring提供的JdbcTemplate实现对用户表的增删改查操作.在实现这个例子的时候,我们事先在MySQL中创建了用户表.创建表的过程我们在实际开发系统的时候会经常使用,但是一直有一个问题存在,由于一个系统的程序版本通过git得到了很好的版本控制,而数据库结构并没有,即使我们通过Git进行了语句的版本化,那么在各个环境的数据库中如何做好版本管理呢?下面我们就通过本文来学习一下在Spring B

  • 详解spring boot rest例子

    简介:本文将帮助您使用 Spring Boot 创建简单的 REST 服务. 你将学习 什么是 REST 服务? 如何使用 Spring Initializr 引导创建 Rest 服务应用程序? 如何创建获取 REST 服务以检索学生注册的课程? 如何为学生注册课程创建 Post REST 服务? 如何利用 postman 执行 rest 服务? 本教程使用的 rest 服务 在本教程中,我们将使用适当的 URI 和 HTTP 方法创建三个服务: @GetMapping("/ students

  • 详解spring boot starter redis配置文件

    spring-boot-starter-Redis主要是通过配置RedisConnectionFactory中的相关参数去实现连接redis service. RedisConnectionFactory是一个接口,有如下4个具体的实现类,我们通常使用的是JedisConnectionFactory. 在spring boot的配置文件中redis的基本配置如下: # Redis服务器地址 spring.redis.host=192.168.0.58 # Redis服务器连接端口 spring.

  • 实例详解Spring Boot实战之Redis缓存登录验证码

    本章简单介绍redis的配置及使用方法,本文示例代码在前面代码的基础上进行修改添加,实现了使用redis进行缓存验证码,以及校验验证码的过程. 1.添加依赖库(添加redis库,以及第三方的验证码库) <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency&

  • 详解Spring boot Admin 使用eureka监控服务

    前言 最近刚好有空,来学习一下如何搭建spring boot admin环境.其中遇到很多的坑. 网上大多都是使用admin-url的方式直接来监控的,感觉一点也不灵活,这不是我想要的结果,所以本篇介绍借助eureka服务注册和发现功能来灵活监控程序. 本文主要记录spring boot admin的搭建过程,希望能有所帮助.其实非常的简单,不要被使用常规方式的误导! 环境介绍 IDE:intellij idea jdk: java8 maven:3.3.9 spring boot:1.5.6

  • 详解spring boot jpa整合QueryDSL来简化复杂操作

    前言 使用过spring data jpa的同学,都很清楚,对于复杂的sql查询,处理起来还是比较复杂的,而本文中的QueryDSL就是用来简化JPA操作的. Querydsl定义了一种常用的静态类型语法,用于在持久域模型数据之上进行查询.JDO和JPA是Querydsl的主要集成技术.本文旨在介绍如何使用Querydsl与JPA组合使用.JPA的Querydsl是JPQL和Criteria查询的替代方法.QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查

  • 详解Spring Boot 目录文件结构

    1.目录结构 src/main/java:存放代码 src/main/resources resources:(Spring Boot 默认的)存放资源文件 static:(Spring Boot 默认的)存放静态文件,比如 css.js.image, (访问方式 http://localhost:8080/js/main.js) public:(Spring Boot 默认的)存放公共文件 templates:(用户自己定义的,可以随便取名,但这里使用公认的文件名)存放静态页面,比如 jsp.

  • 详解Spring Boot 打包分离依赖JAR 和配置文件

    1:自定义路径 <properties> <!--自定义路径--> <directory>d:/im/</directory> </properties> 2:把配置文件打包出来 <build> <plugins> <!--上线部署 JAR启动分离依赖lib和配置--> <!--打包jar--> <plugin> <groupId>org.apache.maven.plugi

  • 详解Spring Boot使用系统参数表提升系统的灵活性

    目录 一.使用系统参数表的好处 二.系统参数表的表结构 三.系统参数表在项目中的使用 3.1.Entity类 3.2.Dao类 3.3.Service类 3.4.ServiceImpl类 3.5.全局配置服务类 3.6.启动时加载 3.7.在服务实现类中访问系统参数 一.使用系统参数表的好处 ​​以数据库表形式存储的系统参数表比配置文件(.properties文件或.yaml文件)要更灵活,因为无需重启系统就可以动态更新. ​系统参数表可用于存储下列数据: 表字段枚举值,如下列字段: `ques

随机推荐