我使用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)
答案 0 :(得分:2)
你试图以一种我不熟悉的方式使用spring和JBheave,甚至可能无法通过相当多的工作(以及来自JBehave内部的知识)来使用它。
有一个明显的问题,即您创建的AdminServiceSteps
实例不是来自Spring上下文。您可以尝试以这种方式替换StepsFactory
@Override
public InjectableStepsFactory stepsFactory() {
return new SpringStepsFactory(configuration(), springContext);
}
班级SpringStepsFactory
是JBehave-spring整合的一部分