JBehave在运行可嵌入的故事时抛出NullPointerException

时间:2017-03-28 17:55:31

标签: java jbehave jbehave-maven-plugin

我正在开发一个Spring MVC休息服务,为此我也试图建立JBehave。这是一个带有单个模块的Maven项目,JBehave代码生活在该模块的test范围内。我的问题是我的样本测试(这只是一个空的测试)失败了NPE。我期待看到测试通过,以便我知道JBehave设置正确。你能看一下我所得到的东西,看看你是否可以帮助我找出造成NPE的原因?

首先,我的maven配置的相关部分:

<properties>
    <jbehave.version>4.0.4</jbehave.version>
</properties>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jbehave</groupId>
        <artifactId>jbehave-core</artifactId>
        <version>${jbehave.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jbehave</groupId>
        <artifactId>jbehave-spring</artifactId>
        <version>${jbehave.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.jbehave.site</groupId>
        <artifactId>jbehave-site-resources</artifactId>
        <version>3.1.1</version>
        <scope>test</scope>
        <type>zip</type>
    </dependency>
    <dependency>
        <groupId>org.jbehave</groupId>
        <artifactId>jbehave-core</artifactId>
        <version>${jbehave.version}</version>
        <classifier>resources</classifier>
        <type>zip</type>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    ...    
    <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <scope>test</scope>
                    <testSourceDirectory>${basedir}/src/test/java/</testSourceDirectory>
                    <testClassesDirectory>${project.build.directory}/test-classes/</testClassesDirectory>
                    <includes>
                        <include>com/mycompany/myproject/test/behavior/steps/*.java</include>
                    </includes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.jbehave</groupId>
                <artifactId>jbehave-maven-plugin</artifactId>
                <version>${jbehave.version}</version>
                <configuration>
                    <scope>test</scope>
                </configuration>
                <executions>
                    <execution>
                        <id>unpack-view-resources</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack-view-resources</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>run-stories-as-embeddables</id>
                        <phase>integration-test</phase>
                        <configuration>
                            <scope>test</scope>
                            <includes>
                                <include>com/mycompany/myproject/test/behavior/steps/*.java</include>
                            </includes>
                            <systemProperties>
                                <property>
                                    <name>java.awt.headless</name>
                                    <value>true</value>
                                </property>
                            </systemProperties>
                        </configuration>
                        <goals>
                            <goal>run-stories-as-embeddables</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                        <version>1.2.17</version>
                        <scope>compile</scope>
                    </dependency>
                </dependencies>
            </plugin>
</build>

我通过mvn clean integration-test -e运行我的测试,我得到了这个输出:

$ mvn clean integration-test -e
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MyProject 0.1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MyProject ---
[INFO] Deleting C:\Users\mylogin\myproject\target
[INFO]
[INFO] --- jbehave-maven-plugin:4.0.4:unpack-view-resources (unpack-view-resources) @ MyProject ---
[INFO] Unpacked C:\Users\mylogin\.m2\repository\org\jbehave\site\jbehave-site-resources\3.1.1\jbehave-site-resources-3.1.1.zip to C:\Users\mylogin\myproject\target\jbehave\view
[INFO] Unpacked C:\Users\mylogin\.m2\repository\org\jbehave\jbehave-core\4.0.4\jbehave-core-4.0.4-resources.zip to C:\Users\mylogin\myproject\target\jbehave\view
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ MyProject ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 18 resources
[INFO] Copying 6 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ MyProject ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 62 source files to C:\Users\mylogin\myproject\target\classes
... omitted ...
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ MyProject ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 6 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ MyProject ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 12 source files to C:\Users\mylogin\myproject\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ MyProject ---
[INFO] Surefire report directory: C:\Users\mylogin\myproject\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=false,verboseFailures=true,verboseFiltering=false,storyTimeouts=300,threads=1,failOnStoryTimeout=false]
Running story com/mycompany/myproject/test/behavior/steps/sample_rest_call_with_invalid_account_steps.story
Generating reports view to 'C:\Users\mylogin\myproject\target\jbehave' using formats '[stats, ide_console, txt, html]' and view properties '{navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, reports=ftl/jbehave-reports.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl, decorated=ftl/jbehave-report-decorated.ftl, maps=ftl/jbehave-maps.ftl}'
Reports view generated with 2 stories (of which 1 pending) containing 1 scenarios (of which 1 pending)
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.326 sec - in com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-war-plugin:3.0.0:war (default-war) @ MyProject ---
[INFO] Packaging webapp
[INFO] Assembling webapp [MyProject] in [C:\Users\mylogin\myproject\target\mywarname##0.1]
[INFO] Processing war project
[INFO] Copying webapp resources [C:\Users\mylogin\myproject\src\main\webapp]
[INFO] Webapp assembled in [484 msecs]
[INFO] Building war: C:\Users\mylogin\myproject\target\mywarname##0.1.war
[INFO]
[INFO] --- spring-boot-maven-plugin:1.3.5.RELEASE:repackage (default) @ MyProject ---
[INFO]
[INFO] --- jbehave-maven-plugin:4.0.4:run-stories-as-embeddables (run-stories-as-embeddables) @ MyProject ---
[INFO] Running stories as embeddables using embedder Embedder[storyMapper=StoryMapper,embedderMonitor=MavenEmbedderMonitor,classLoader=EmbedderClassLoader[urls=[/C:/Users/mylogin/Projects/AQ/aqservices/target/test-classes/, /C:/Users/mylogin/Projects/AQ/aqservices/target/classes/, spring-boot-starter-tomcat-1.3.5.RELEASE.jar, tomcat-embed-core-8.0.33.jar, tomcat-embed-el-8.0.33.jar, tomcat-embed-logging-juli-8.0.33.jar, tomcat-embed-websocket-8.0.33.jar, spring-ws-core-2.3.0.RELEASE.jar, spring-xml-2.3.0.RELEASE.jar, spring-aop-4.2.6.RELEASE.jar, spring-beans-4.2.6.RELEASE.jar, spring-core-4.2.6.RELEASE.jar, spring-oxm-4.2.6.RELEASE.jar, spring-web-4.2.6.RELEASE.jar, spring-webmvc-4.2.6.RELEASE.jar, spring-boot-starter-1.3.5.RELEASE.jar, spring-boot-1.3.5.RELEASE.jar, spring-boot-autoconfigure-1.3.5.RELEASE.jar, snakeyaml-1.16.jar, spring-boot-starter-log4j-1.3.7.RELEASE.jar, jcl-over-slf4j-1.7.21.jar, jul-to-slf4j-1.7.21.jar, slf4j-log4j12-1.7.21.jar, log4j-1.2.17.jar, spring-orm-4.3.2.RELEASE.jar, spring-jdbc-4.2.6.RELEASE.jar, spring-tx-4.2.6.RELEASE.jar, spring-data-commons-1.12.2.RELEASE.jar, spring-context-4.2.6.RELEASE.jar, spring-expression-4.2.6.RELEASE.jar, spring-context-support-4.1.4.RELEASE.jar, spring-test-4.2.6.RELEASE.jar, spring-security-core-4.1.1.RELEASE.jar, aopalliance-1.0.jar, spring-security-web-4.1.1.RELEASE.jar, spring-security-config-4.1.1.RELEASE.jar, jstl-1.2.jar, wsdl4j-1.6.3.jar, aspectjweaver-1.8.9.jar, jasypt-1.9.2.jar, xstream-1.4.9.jar, xmlpull-1.1.3.1.jar, xpp3_min-1.1.4c.jar, bcprov-jdk16-1.46.jar, org.apache.commons.io-2.4.jar, commons-io-2.4.jar, slf4j-api-1.7.21.jar, commons-lang-2.6.jar, mail-1.4.jar, activation-1.1.jar, dozer-5.5.1.jar, commons-beanutils-1.9.2.jar, commons-lang3-3.2.1.jar, jregex-1.2_01.jar, tomcat-embed-jasper-8.0.33.jar, ecj-4.5.jar, ehcache-2.10.2.2.21.jar, HikariCP-2.4.7.jar, emdq-1.0.jar, sqljdbc4-4.0.jar, ghs-verifyaq-client-1.0.3.jar, mockito-all-1.9.5.jar, junit-4.11.jar, hamcrest-core-1.3.jar, jbehave-core-4.0.4.jar, hamcrest-library-1.3.jar, hamcrest-integration-1.3.jar, commons-collections-3.2.2.jar, plexus-utils-3.0.10.jar, freemarker-2.3.23.jar, paranamer-2.4.jar, jbehave-spring-4.0.4.jar],parent=ClassRealm[plugin>org.jbehave:jbehave-maven-plugin:4.0.4, parent: sun.misc.Launcher$AppClassLoader@55f96302]],embedderControls=UnmodifiableEmbedderControls[EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeouts=300,threads=1,failOnStoryTimeout=false]],embedderFailureStrategy=<null>,configuration=org.jbehave.core.configuration.MostUsefulConfiguration@645b2ac7,candidateSteps=<null>,stepsFactory=<null>,metaFilters=<null>,metaMatchers=<null>,systemProperties={java.awt.headless=true},executorService=<null>,executorServiceCreated=false,performableTree=PerformableTree,storyManager=<null>,timeoutParsers=<null>]
[INFO] Found class names: [com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps]
[INFO] Using controls UnmodifiableEmbedderControls[EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeouts=300,threads=1,failOnStoryTimeout=false]]
[INFO] Running embeddable com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps
[INFO] Processing system properties {java.awt.headless=true}
[INFO] System property 'java.awt.headless' set to 'true'
[INFO] Using controls UnmodifiableEmbedderControls[EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=false,ignoreFailureInView=false,verboseFailures=false,verboseFiltering=false,storyTimeouts=300,threads=1,failOnStoryTimeout=false]]
[INFO] Generating reports view to 'C:\Users\mylogin\myproject\target\jbehave' using formats '[stats, ide_console, txt, html]' and view properties '{navigator=ftl/jbehave-navigator.ftl, views=ftl/jbehave-views.ftl, reports=ftl/jbehave-reports.ftl, nonDecorated=ftl/jbehave-report-non-decorated.ftl, decorated=ftl/jbehave-report-decorated.ftl, maps=ftl/jbehave-maps.ftl}'
[INFO] Reports view generated with 2 stories (of which 1 pending) containing 1 scenarios (of which 1 pending)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12.714 s
[INFO] Finished at: 2017-03-28T13:25:28-04:00
[INFO] Final Memory: 38M/299M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.jbehave:jbehave-maven-plugin:4.0.4:run-stories-as-embeddables (run-stories-as-embeddables) on project MyProject: Failed to run stories as embeddables: Failure in running embeddable: com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps: NullPointerException -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.jbehave:jbehave-maven-plugin:4.0.4:run-stories-as-embeddables (run-stories-as-embeddables) on project MyProject: Failed to run stories as embeddables
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoFailureException: Failed to run stories as embeddables
        at org.jbehave.mojo.RunStoriesAsEmbeddables.execute(RunStoriesAsEmbeddables.java:20)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
        ... 20 more
Caused by: org.jbehave.core.embedder.Embedder$RunningEmbeddablesFailed: Failure in running embeddable: com.mycompany.myproject.test.behavior.steps.SampleRestCallWithInvalidAccountSteps
        at org.jbehave.core.embedder.Embedder.runAsEmbeddables(Embedder.java:140)
        at org.jbehave.mojo.RunStoriesAsEmbeddables.execute(RunStoriesAsEmbeddables.java:18)
        ... 22 more
Caused by: java.lang.NullPointerException
        at org.jbehave.core.steps.spring.SpringStepsFactory.stepsTypes(SpringStepsFactory.java:39)
        at org.jbehave.core.steps.AbstractStepsFactory.createCandidateSteps(AbstractStepsFactory.java:34)
        at org.jbehave.core.embedder.PerformableTree$RunContext.<init>(PerformableTree.java:458)
        at org.jbehave.core.embedder.PerformableTree.newRunContext(PerformableTree.java:1105)
        at org.jbehave.core.embedder.StoryManager.runStories(StoryManager.java:100)
        at org.jbehave.core.embedder.StoryManager.runStoriesAsPaths(StoryManager.java:86)
        at org.jbehave.core.embedder.Embedder.runStoriesAsPaths(Embedder.java:213)
        at org.jbehave.core.junit.JUnitStory.run(JUnitStory.java:24)
        at org.jbehave.core.embedder.Embedder.runAsEmbeddables(Embedder.java:131)
        ... 23 more
[ERROR]
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

我的故事档案,名为sample_rest_call_with_invalid_account_steps.story

Scenario: Call the sample rest resource
Given an initial value
When this API is called
Then expect failure

我的java故事类,名为SampleRestCallWithInvalidAccountSteps.java

import com.mycompany.myproject.test.behavior.driver.AbstractSpringJBehaveStory;
import com.mycompany.myproject.test.behavior.driver.annotations.BehaviorTest;

import org.jbehave.core.annotations.*;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


/**
 * Scenario: Call the sample rest resource
 */
@RunWith(SpringJUnit4ClassRunner.class)
@BehaviorTest
public class SampleRestCallWithInvalidAccountSteps extends AbstractSpringJBehaveStory {

    @Given("an initial value")
    public void Given() {
        // purposely empty
    }

    @When("this API is called")
    public void When() {
        // purposely empty
    }

    @Then("expect failure")
    public void Then() {
        // purposely empty
    }
}

我的故事超类:

package com.mycompany.myproject.test.behavior.driver;

import java.util.Arrays;

import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.embedder.Embedder;
import org.jbehave.core.embedder.EmbedderControls;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryLoader;
import org.jbehave.core.io.StoryPathResolver;
import org.jbehave.core.io.UnderscoredCamelCaseResolver;
import org.jbehave.core.junit.JUnitStory;
import org.jbehave.core.reporters.FilePrintStreamFactory;
import org.jbehave.core.reporters.Format;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.ParameterControls;
import org.jbehave.core.steps.spring.SpringStepsFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;


public abstract class AbstractSpringJBehaveStory extends JUnitStory {

    @Autowired
    private ApplicationContext appContext;

    public AbstractSpringJBehaveStory() {
        Embedder embedder = new Embedder();
        embedder.useEmbedderControls(embedderControls());
        embedder.useMetaFilters(Arrays.asList("-skip"));
        useEmbedder(embedder);
    }

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new SpringStepsFactory(configuration(), appContext);
    }

    @Override
    public Configuration configuration() {
        return new MostUsefulConfiguration()
                .useStoryPathResolver(storyPathResolver())
                .useStoryLoader(storyLoader())
                .useStoryReporterBuilder(storyReporterBuilder())
                .useParameterControls(parameterControls());
    }

    private EmbedderControls embedderControls() {
        return new EmbedderControls()
                .doIgnoreFailureInStories(true)
                .doGenerateViewAfterStories(true)
                .doVerboseFailures(true);
    }

    private StoryPathResolver storyPathResolver() {
        return new UnderscoredCamelCaseResolver();
    }

    private StoryLoader storyLoader() {
        return new LoadFromClasspath();
    }

    private StoryReporterBuilder storyReporterBuilder() {
        return new StoryReporterBuilder()
                .withCodeLocation(CodeLocations.codeLocationFromClass(this.getClass()))
                .withPathResolver(new FilePrintStreamFactory.ResolveToPackagedName())
                .withFailureTrace(true)
                .withDefaultFormats()
                .withFormats(Format.IDE_CONSOLE, Format.TXT, Format.HTML);
    }

    private ParameterControls parameterControls() {
        return new ParameterControls()
                .useDelimiterNamedParameters(true);
    }
}

作为参考,我松散地关注this guide

1 个答案:

答案 0 :(得分:0)

我现在有一个有效的解决方案。我相信我已经缩小了罪魁祸首,在AbstractSpringJBehaveStory班级中不正当地延长SampleRestCallSteps。我通过创建一个新的空类来作为AbstractSpringJBehaveStory的可实例化子类并从extends中删除SampleRestCallSteps来修复此问题。

另外,我在创建配置时确实找到了一些缺失的行,我认为这是真正的原因。我从下面的方法中看到了新的,用maven生成一个空白的新JBehave-Spring原型。

@Override
public Configuration configuration() {
    ParameterConverters parameterConverters = new ParameterConverters();
    ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(
            new LocalizedKeywords(),
            new LoadFromClasspath(this.getClass()),
            parameterConverters);
    parameterConverters.addConverters(
            new DateConverter(new SimpleDateFormat("yyyy-MM-dd")),
            new ExamplesTableConverter(examplesTableFactory));
    return new MostUsefulConfiguration()
            .useStoryLoader(storyLoader())
            .useStoryParser(new RegexStoryParser(examplesTableFactory))
            .useStoryReporterBuilder(storyReporterBuilder())
            .useStoryPathResolver(storyPathResolver())
            .useParameterControls(parameterControls())
            .useParameterConverters(parameterConverters);
}

最后,我认为Spring上下文没有正确自动装配,所以我更改了stepsFactory()这样的方法(再次从maven模板中复制):

@Override
public InjectableStepsFactory stepsFactory() {
    ApplicationContext appContext = new SpringApplicationContextFactory("jbehave-app-context.xml")
            .createApplicationContext();
    return new SpringStepsFactory(configuration(), appContext);
}