【问题标题】:Request-scoped beans not working in Spring tests with Cucumber请求范围的 bean 在 Cucumber 的 Spring 测试中不起作用
【发布时间】:2020-12-02 01:07:42
【问题描述】:

我有一个基于 Spring 4.3.28 的应用程序(即不是 Spring Boot!),我想将我的集成测试迁移到 Cucumber。

我已经关注了这个tutorial 并将其改编为普通的 Spring。

到目前为止,我编写的测试工作正常(Spring 上下文已初始化等),但一旦涉及请求范围的 bean,它们就会停止工作:

Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you
referring to request attributes outside of an actual web request, or processing a 
request outside of the originally receiving thread? If you are actually operating 
within a web request and still receive this message, your code is probably running 
outside of DispatcherServlet/DispatcherPortlet: In this case, use 
RequestContextListener or RequestContextFilter to expose the current request.

我创建了一个小的sample project 试图重现问题。

有一个名为 AppConfig 的上下文配置类:


@Configuration
public class AppConfig {
   @Bean
   @Scope("request“) // when this line is removed, the test succeeds
   public ExampleService exampleService() {
      return new ExampleService();
   }

   @Bean("dependency")
   @Scope("request") // when this line is removed, the test succeeds
   public String dependencyBean() {
      return "dependency bean";
   }
}

ExampleService 是请求范围的,并获得一个由@Autowired 注入的请求范围的bean:

public class ExampleService {

  @Autowired
  @Qualifier("dependency")
  String dependencyBean;

  public String process() { return "I have a "+dependencyBean; }
}

对于测试,我有一个带有 Spring 注释的超类:

@ContextConfiguration(classes = AppConfig.class)
@CucumberContextConfiguration
@WebAppConfiguration
public class TestBase {

  @Autowired
  public ExampleService underTest;
}

还有一个运行良好的普通 Spring 测试:

@RunWith(SpringRunner.class)
public class ExampleServicePlainSpringTest extends TestBase {

  @Test
  public void whenProcessingDataThenResultShouldBeReturned() {
    assertThat(this.underTest.process()).isEqualTo("I have a dependency bean");
  }

}

Cucumber 测试由这个测试类存根执行:

@RunWith(Cucumber.class)
public class ExampleServiceCucumberTest extends TestBase {}

实际的黄瓜步骤定义在这里:

public class CucumberStepDefinitions extends TestBase {

  private String result;

  @When("I process data")
  public void iProcessData() {
    result = this.underTest.process();
  }

  @Then("the result should be returned")
  public void checkResult() {
    assertThat(result).isEqualTo("I have a dependency bean");
  }
}

Cucumber 的 .feature 文件位于 src/test/resources 目录下,与步骤定义类同名:

Feature: Example

  Scenario: Example service bean returns dependency
    When I process data
    Then the result should be returned

通常当我遇到“no thread-bound request found”错误时,这是​​因为 @WebAppConfiguration 注释丢失,或者当我尝试将请求范围的 bean 注入非请求范围的 bean 时。但这里不是这样。 我做错了什么?

【问题讨论】:

  • 一目了然一切都是正确的。 Cucumber 使用 Springs TestContextManager 但不会触发其 before/after 方法挂钩,因为 Cucumber 没有单一方法。您可能必须在测试中创建请求上下文或向 Cucumber 提交修复。

标签: java spring cucumber


【解决方案1】:

我能够弄清楚如何解决它;更新后的代码位于问题中链接的 github 存储库中。

使用SpringRunner 时,请求上下文在ServletTestExecutionListener 中初始化,该ServletTestExecutionListener 隐式添加到TestExecutionListeners 列表中以进行测试。 初始化发生在该侦听器的beforeTestMethod() 方法中。

但是,正如 @M.P.Korsanje 在 cmets 中正确指出的那样(谢谢!),Cucumber 没有测试方法,因此永远不会执行 beforeTestMethod()

我的解决方案是将ServletTestExecutionListener 的自定义子类添加为TestExecutionListener,它将beforeTestClass() 调用委托给beforeTestMethod()

public class ClassLevelServletTestExecutionListener extends ServletTestExecutionListener {

  @Override
  public void beforeTestClass(TestContext testContext) throws Exception {
    super.beforeTestMethod(testContext);
  }

  @Override
  public void afterTestClass(TestContext testContext) throws Exception {
    super.afterTestMethod(testContext);
  }
}

ExampleServiceCucumberTest:

@ContextConfiguration(classes = {AppConfig.class})
@CucumberContextConfiguration
@WebAppConfiguration
@TestExecutionListeners(ClassLevelServletTestExecutionListener.class)
// extend the Spring class to get the default TestExecutionListeners
public class TestBase extends AbstractJUnit4SpringContextTests {

  @Autowired
  public ExampleService underTest;
}

【讨论】:

  • 不错的技巧!你介意在 github 上创建一个问题吗?我认为这应该得到适当的支持而无需破解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 2011-01-25
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
  • 2011-08-19
相关资源
最近更新 更多