虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > Java编程 > spring boot整合Cucumber(BDD)的方法

spring boot整合Cucumber(BDD)的方法
类别:Java编程   作者:码皇   来源:互联网   点击:

本篇文章主要介绍了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测试配置介绍详解
相关热词搜索: spring boot整合Cucumber spring boot Cuc