spring boot整合Cucumber(BDD)的方法

本文介绍了spring boot整合Cucumber(BDD)的方法,分享给大家,具体如下:

1、新建一个springboot工程工程结构如下:

2、添加pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion> 

  <groupId>com.chhliu</groupId>
  <artifactId>spring-boot-cucumber</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging> 

  <name>spring-boot-cucumber</name>
  <description>Demo project for Spring Boot and Cucumber</description> 

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent> 

  <properties>
    <cucumber.version>1.2.4</cucumber.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.7</java.version>
  </properties> 

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency> 

    <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>
    <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-core</artifactId>
      <version>${cucumber.version}</version>
    </dependency>
    <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-spring</artifactId>
      <version>${cucumber.version}</version>
    </dependency>
    <dependency>
      <groupId>info.cukes</groupId>
      <artifactId>cucumber-junit</artifactId>
      <version>${cucumber.version}</version>
      <exclusions>
        <exclusion>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
        </exclusion>
      </exclusions>
    </dependency> 

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies> 

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin> 

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
        <executions>
          <execution>
            <phase>integration-test</phase>
            <goals>
              <goal>java</goal>
            </goals>
            <configuration>
              <classpathScope>test</classpathScope>
              <mainClass>com.chhliu.test.CucumberTest.java</mainClass>
              <arguments>
                <argument>--plugin</argument>
                <argument>pretty</argument>
                <argument>--glue</argument>
                <argument>src/test/resources/</argument>
              </arguments>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project> 

2、编写service接口及其实现类

package com.chhliu.service; 

/**
 * 模拟登录
 * @author chhliu
 *
 */
public interface UserInfoServiceI {
  boolean login(String username, String password, String confirmPassword);
} 
package com.chhliu.service;
import org.springframework.stereotype.Service;
@Service("userInfoService")
public class UserInfoService implements UserInfoServiceI{
  public boolean login(String username, String password, String confirmPassword){
    return (username.equals("chhliu") && password.equals("123456") && confirmPassword.equals("123456"));
  }
} 

3、编写feature文件

#language: zh-CN
#"zh-CN": {
#  "but": "*|但是<",
#  "and": "*|而且<|并且<|同时<",
#  "then": "*|那么<",
#  "when": "*|当<",
#  "name": "Chinese simplified",
#  "native": "简体中文",
#  "feature": "功能",
#  "background": "背景",
#  "scenario": "场景|剧本",
#  "scenario_outline": "场景大纲|剧本大纲",
#  "examples": "例子",
#  "given": "*|假如<|假设<|假定<"
# } 

@bank
功能:假如我在银行取钱的时候,如果我登录成功并且输入的密码正确,那么会显示我的银行卡余额,假如余额为50万
  场景:银行取钱
    假如:我以"chhliu"登录
    并且:输入的密码为"123456"
    当:确认密码也为"123456"时
    那么:显示银行卡余额为"500000" 

4、编写测试类

package com.chhliu.test;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber; 

/**
 * @RunWith(Cucumber.class) 这是一个运行器 ,指用Cucumber来运行测试
 * @CucumberOptions中的features,用于指定我们项目中要运行的feature的目录
 * @CucumberOptions中的format,用于指定我们项目中要运行时生成的报告,并指定之后可以在target目录中找到对应的测试报告
 * @CucumberOptions中的glue,用于指定项目运行时查找实现step定义文件的目录
 *
 * 在实际项目中,随着项目的进行,一个测试工程可能由多个feature文件组成,并且每个feature文件中可能也是由多个scenario组成。默认情况下,
 * 每次运行是运行所有feature中的所有scenario。这样可能导致正常情况下运行一次测试脚本,需要非常长的时间来等待测试结果。
 * 但是实际过程中,测试用例是有优先级等区分的。比如smokeTest、regressionTest等。或者有时候会有特别小部分的用例,比如等级是critical,
 * 这些用例需要长时间运行来监测系统是否没有白页或者页面404等现象。
 * 所以我们必须区分开所有的scenario,可以使我们在启动测试脚本时,可以根据我们需要来运行哪些模块的scenaro。这时我们可以使用Tags
 * 在Cucumber里Tag是直接在Feature、Scenari或Scenario Outline关键字前给feature或scenario添加任意数量的前缀为@的tags,多个tag用空格来分隔
 * @author chhliu
 *
 */
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"json:target/cucumber.json", "pretty"}, features = "src/test/resources")
public class CucumberTest {
}

5、运行测试类,并对测试输出的未定义步骤进行完善

package com.chhliu.test;
import javax.annotation.Resource;
import org.junit.Assert;
import com.chhliu.service.UserInfoServiceI;
import cucumber.api.java.zh_cn.假如;
import cucumber.api.java.zh_cn.当;
import cucumber.api.java.zh_cn.那么;
public class Cucumber集成spring { 

  @Resource(name="userInfoService")
  private UserInfoServiceI service; 

  private String username; 

  private String password; 

  private String confirmPassword; 

  @假如("^:我以\"([^\"]*)\"登录$")
  public void 我以_登录(String arg1) throws Throwable {
    this.username = arg1;
  } 

  @假如("^:输入的密码为\"([^\"]*)\"$")
  public void 输入的密码为(String arg1) throws Throwable {
    this.password = arg1;
  } 

  @当("^:确认密码也为\"([^\"]*)\"时$")
  public void 确认密码也为_时(String arg1) throws Throwable {
    this.confirmPassword = arg1;
  } 

  @那么("^:显示银行卡余额为\"([^\"]*)\"$")
  public void 显示银行卡余额为(String arg1) throws Throwable {
    boolean isLogin = service.login(username, password, confirmPassword);
    if(isLogin){
      System.out.println("登录成功!查询余额如下:"+arg1);
      Assert.assertEquals("500000", arg1);
    }
  }
}

6、在测试步骤上添加注解支持

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration // 不加此注解,bean会注入不进去
@SpringBootTest // 不加此注解会找不到bean
public class Cucumber集成spring{
} 

7、测试结果

2 Scenarios (2 passed) 
11 Steps (11 passed) 
0m0.091s

8、整合注意点

spring boot与Cucumber整合的时候,有个地方需要注意,因为spring boot提倡去xml化,所以传统方式下,Cucumber会读取classpath下的cucumber.xml配置文件来初始化bean的方式,和spring整合后,就不能用这种方式了,需要使用@ContextConfiguration注解来实现类的加载,如果是需要加载配置文件的方式的话,可以如下使用:

@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 

如果使用注解的方式来整合的话,使用如下:

@ContextConfiguration(classes=SpringBootCucumberApplication.class) 

或者直接

@ContextConfiguration

特别注意:@ContextConfiguration注解必加,否则会出现bean注入失败

下面,我们从源码来看下为什么会造成这种情况。

该部分涉及的代码都在cucumber-spring包下的SpringFactory类中,重点我们看下下面这个类:

public void start() {// cucumber测试启动方法
    if (stepClassWithSpringContext != null) {// 如果使用了@ContextConfiguration注解的话,此处不为null
      testContextManager = new CucumberTestContextManager(stepClassWithSpringContext);
    } else {// 否则stepClassWithSpringContext就为null,会进入下面这个分支
      if (beanFactory == null) {
        beanFactory = createFallbackContext();// 这个方法是我们要跟的重点
      }
    }
    notifyContextManagerAboutTestClassStarted();
    if (beanFactory == null || isNewContextCreated()) {
      beanFactory = testContextManager.getBeanFactory();
      for (Class<?> stepClass : stepClasses) {
        registerStepClassBeanDefinition(beanFactory, stepClass);
      }
    }
    GlueCodeContext.INSTANCE.start();
  }

我们在来跟下createFallbackContext方法:

private ConfigurableListableBeanFactory createFallbackContext() {
    ConfigurableApplicationContext applicationContext;
    if (getClass().getClassLoader().getResource("cucumber.xml") != null) {// 会先根据classpath下的cucumber.xml来初始化<span style="font-family:Arial, Helvetica, sans-serif;">ConfigurableApplicationContext</span>
      applicationContext = new ClassPathXmlApplicationContext("cucumber.xml");
    } else {// 如果没有配置cucumber.xml的话,会new GenericApplicationContext
      applicationContext = new GenericApplicationContext();
    }
    applicationContext.registerShutdownHook();
    ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
    beanFactory.registerScope(GlueCodeScope.NAME, new GlueCodeScope());
    for (Class<?> stepClass : stepClasses) {
      registerStepClassBeanDefinition(beanFactory, stepClass);
    }
    return beanFactory;
  }

最后,来说下GenericApplicationContext这个类,该类会根据Bean的Type类型,然后newInstance实例,但是由于这个类中又注入了其他的类,而注入的类是无法通过new实例的方式来初始化的,所以最后就会注入失败,报空指针了。

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

您可能感兴趣的文章:

  • Springboot Cucumber测试配置介绍详解
(0)

相关推荐

  • Springboot Cucumber测试配置介绍详解

    目前Spring-boot成为了java开发的主流框架,Cucumber作为一款支持dsl的自动化测试工具,很适合用户编写DSL优化过的单元测试等测试用例.本文将讲解如何在SpringBoot中配置Cucumber进行自动化测试. 目录结构如下: gradle相关配置如下所示: testCompile('org.springframework.boot:spring-boot-starter-test', "info.cukes:cucumber-jvm:1.1.8", "i

  • spring boot整合Cucumber(BDD)的方法

    本文介绍了spring boot整合Cucumber(BDD)的方法,分享给大家,具体如下: 1.新建一个springboot工程工程结构如下: 2.添加pom依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLS

  • spring boot整合netty的实现方法

    之前花了几天去研究怎么使用netty做一个网关服务器,虽然最后还是没能用上我做的网关,但是呢netty是会用了,总结一下netty和spring boot整合.感觉不用spring boot都不会写代码了.哈哈哈 在pom文件中添加相关的依赖,这里主要的就是netty的依赖,spring boot的相关依赖本文不提 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artif

  • spring boot整合quartz实现多个定时任务的方法

    最近收到了很多封邮件,都是想知道spring boot整合quartz如何实现多个定时任务的,由于本人生产上并没有使用到多个定时任务,这里给个实现的思路. 1.新建两个定时任务,如下: public class ScheduledJob implements Job{ @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("sched

  • Spring Boot 整合mybatis 使用多数据源的实现方法

    前言 本篇教程偏向实战,程序猿直接copy代码加入到自己的项目中做简单的修修改改便可使用,而对于springboot以及mybatis不在此进行展开介绍,如有读者希望了解可以给我留言,并持续关注,我后续会慢慢更新.(黑色区域代码部分,安卓手机可手动向左滑动,来查看全部代码) 整合 其实整合很简单,如果是用gradle的话,在build.gradle文件里加入 compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')

  • Spring Boot整合JPA使用多个数据源的方法步骤

    介绍 JPA(Java Persistence API)Java 持久化 API,是 Java 持久化的标准规范,Hibernate 是持久化规范的技术实现,而 Spring Data JPA 是在 Hibernate 基础上封装的一款框架. 第一次使用 Spring JPA 的时候,感觉这东西简直就是神器,几乎不需要写什么关于数据库访问的代码一个基本的 CURD 的功能就出来了.在这篇文章中,我们将介绍 Spring Boot 整合 JPA 使用多个数据源的方法. 开发环境: Spring B

  • Spring Boot 整合 JWT的方法

    1.JWT 是什么? JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法.JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名. 简单来说,就是通过一定规范来生成 token,然后可以通过解密算法逆向解密 token,这样就可以获取用户信息. 优点: 1)生产的 token 可以包含基本信息,比如 id.用户昵称.头像等信息,避免再次查库 2)存储在客户端,不占用服务端的内存资源 缺点: token 是经过 base6

  • Spring Boot整合mybatis使用注解实现动态Sql、参数传递等常用操作(实现方法)

    前面介绍了Spring Boot 整合mybatis 使用注解的方式实现数据库操作,介绍了如何自动生成注解版的mapper 和pojo类. 接下来介绍使用mybatis 常用注解以及如何传参数等数据库操作中的常用操作. 其实,mybatis 注解方式 和 XML配置方式两者的使用基本上相同,只有在构建 SQL 脚本有所区别,所以这里重点介绍两者之间的差异,以及增删改查,参数传递等注解的常用操作. 详解SpringBoot 快速整合Mybatis(去XML化+注解进阶)已经介绍过了,不清楚的朋友可

  • Spring Boot整合Lombok的方法详解

    上篇文章给大家介绍了,喜欢的朋友点击查看下. SpringBoot 开发提速神器 Lombok+MybatisPlus+SwaggerUI Lombok为啥这么牛逼?SpringBoot和IDEA官方都要支持它 一.Lombok简介 Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注释实现这一目的.通过在开发环境中实现  Lombok,开发人员可以节省构建诸如 hashCode() 和 equals() 这样

  • spring boot整合mybatis利用Mysql实现主键UUID的方法

    前言 本文主要给大家介绍了关于spring boot整合mybatis利用Mysql实现主键UUID的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现 基础项目的pom.xml部分代码如下 <properties> <java.version>1.8</java.version> </properties> <!-- Inherit defaults from Spring Boot --> <parent&

  • spring boot整合jsp及设置启动页面的方法

    前言 这几天在集中学习Spring boot+Shiro框架,因为之前view层用jsp比较多,所以想在spring boot中配置jsp,但是spring boot官方不推荐使用jsp,因为jsp相对于一些模板引擎,性能都比较低,官方推荐使用thymeleaf,但是Spring boot整合jsp的过程已经完成,在这里记录一下. 本文基于springboot2.0.4最新版本 spring官方推荐Thymeleaf但是还是有很多javaweb朋友习惯使用jsp虽然现在jsp有点out.本节教程

随机推荐