Spring MVC和JBehave。无法在* Steps.java类中获取@Autowired bean

时间:2015-04-11 11:41:40

标签: spring-mvc autowired jbehave

我使用Spring MVC已经有一段时间了,并且使用了JUnit。当我测试服务或dao时,我使用@Autowired注释来注入豆子,它运作良好。请注意,我在测试和应用程序中使用相同的配置文件,以避免在部署测试运行后配置错误。

现在我必须使用JBehave进行服务层测试。我的Spring MVC已经有了域,DAO和服务层的包。我还为DAO和服务创建了示例JUnit测试。但JBehave没有运气。我使用了来自http://jbehave.org/的“五步概述”,并且能够在没有@Autowired bean的情况下运行JBehave测试,并且它成功运行,生成报告等等。现在我想将DAO和Service层中的@Autowired bean添加到* Steps.java,但似乎它们没有在运行时实例化。

我也用Google搜索并查看http://jbehave.org/中的Spring示例,但我发现不起作用,jbehave.org的示例对我来说看起来很混乱。

所以现在我在Spring Tool Suite(Eclipse)的MAVEN上构建了Spring MVC,Hibernate,JUnit,JBehave。问题是:如何在* Steps.java类中为JBehave测试创建@Autowired对象。

我不确定我要把这些数据放在这里,所以如果有什么不足请告诉我,我会加上它。

admin_service_story.story

Scenario: There is 0 in DB

Given In database there are 0 goods
When The controller calls list method of service
Then service returns with 0 elements list

AdminServiceStory.java //我将其作为JUnit测试

运行
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/META-INF/spring/root-context.xml")
public class AdminServiceStory extends JUnitStory{

    private final CrossReference xref = new CrossReference();

    public AdminServiceStory() {
        configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true)
                .doIgnoreFailureInView(true).useThreads(2).useStoryTimeoutInSecs(60);
        // Uncomment to set meta filter, which can also be set via Ant or Maven
        // configuredEmbedder().useMetaFilters(Arrays.asList("+theme parametrisation"));
    }

    @Override
    public Configuration configuration() {
        Class<? extends Embeddable> embeddableClass = this.getClass();
        Properties viewResources = new Properties();
        viewResources.put("decorateNonHtml", "true");
        // Start from default ParameterConverters instance
        ParameterConverters parameterConverters = new ParameterConverters();
        // factory to allow parameter conversion and loading from external
        // resources (used by StoryParser too)
        ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(new LocalizedKeywords(),
                new LoadFromClasspath(embeddableClass), parameterConverters);
        // add custom converters
        parameterConverters.addConverters(new DateConverter(new SimpleDateFormat("yyyy-MM-dd")),
                new ExamplesTableConverter(examplesTableFactory));

        return new MostUsefulConfiguration()
                .useStoryControls(new StoryControls().doDryRun(false).doSkipScenariosAfterFailure(false))
                .useStoryLoader(new LoadFromClasspath(embeddableClass))
                .useStoryParser(new RegexStoryParser(examplesTableFactory))
                .useStoryPathResolver(new UnderscoredCamelCaseResolver())
                .useStoryReporterBuilder(
                        new StoryReporterBuilder()
                                .withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
                                .withDefaultFormats().withPathResolver(new ResolveToPackagedName())
                                .withViewResources(viewResources).withFormats(Format.CONSOLE, Format.STATS, Format.TXT, Format.HTML, Format.XML)
                                .withFailureTrace(true).withFailureTraceCompression(true).withCrossReference(xref))
                .useParameterConverters(parameterConverters)
                // use '%' instead of '$' to identify parameters
                .useStepPatternParser(new RegexPrefixCapturingPatternParser("%"))
                .useStepMonitor(xref.getStepMonitor());
    }

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(configuration(), new AdminServiceSteps());
    }
}

AdminServiceSteps.java

我用异常标记了字符串:goodDAO.save(good); // !!!这里发生异常java.lang.NullPointerException !!!

@Component
public class AdminServiceSteps {
    private static final String CATALOG_NUMBER_PREFIX = "Num_";
    private static final String NAME_PREFIX = "Good name_";
    private static final String DESCRIPTION_PREFIX = "Description_";

    @Autowired
    private AdminService adminService;

    @Autowired
    private GoodDAO goodDAO;

    List<Good> goodsList;

    @Transactional
    @Given("In database there are %num goods")
    public void putGoodsInDB(int num) {
        Good good;
        for (Integer i = 0; i< num; i++){
            good = new Good();
            good.setCatalogNumber(CATALOG_NUMBER_PREFIX+Integer.toString(i));
            good.setDescription(DESCRIPTION_PREFIX+Integer.toString(i));
            good.setName(NAME_PREFIX+Integer.toString(i));
            goodDAO.save(good);//!!! here exception occurs java.lang.NullPointerException !!!
        }
    }

    //@Transactional
    @When("The controller calls list method of service")
    public void controllerCallsList() {
        //goodsList = adminService.list();
    }

    @Then("service returns with %num elements list")
    public void checkGoodsListSize(int num) {
        //assertEquals("Assert list size", num, goodsList.size());
    }
}

Augusto感谢您的想法。让我们来看看发生了什么。我改变了

public class AdminServiceStory extends JUnitStory implements ApplicationContextAware {

在课堂上:

...

    ApplicationContext springContext; 

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

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        springContext = applicationContext;
    }

当我查看调试器时,看起来InjectableStepsFactory()在setApplicationContext()之前运行,因此springContext变量尚未设置。

所以我得到了

java.lang.NullPointerException
    at org.jbehave.core.steps.spring.SpringStepsFactory.stepsTypes(SpringStepsFactory.java:32)
    at org.jbehave.core.steps.AbstractStepsFactory.createCandidateSteps(AbstractStepsFactory.java:34)
    at org.jbehave.core.embedder.StoryManager.runBeforeOrAfterStories(StoryManager.java:90)
    at org.jbehave.core.embedder.StoryManager.runStories(StoryManager.java:75)
    at org.jbehave.core.embedder.Embedder.runStoriesAsPaths(Embedder.java:203)
    at org.jbehave.core.junit.JUnitStory.run(JUnitStory.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

1 个答案:

答案 0 :(得分:2)

你试图以一种我不熟悉的方式使用spring和JBheave,甚至可能无法通过相当多的工作(以及来自JBehave内部的知识)来使用它。

有一个明显的问题,即您创建的AdminServiceSteps实例不是来自Spring上下文。您可以尝试以这种方式替换StepsFactory

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

班级SpringStepsFactory是JBehave-spring整合的一部分