我正在尝试使用spring cucumber jvm为我们的服务测试rest API的spring rest文档,但在我尝试执行场景时最终会出现一个空指针,因为框架无法初始化Junit上下文。 / p>
错误讯息:
>>> fo={'engine': 'diesel'}
>>> filter(lambda d: all(d[e]==fo[e] for e in fo if e in d), inv)
[{'color': 'red', 'engine': 'diesel', 'type': 'car'}, {'color': 'red', 'engine': 'diesel', 'type': 'truck'}]
代码:
java.lang.NullPointerException at
org.springframework.restdocs.ManualRestDocumentation.beforeOperation(ManualRestDocumentation.java:90) at
org.springframework.restdocs.JUnitRestDocumentation.beforeOperation(JUnitRestDocumentation.java:76)
步骤定义代码:
private AppProperties props;
@Before("@rest") public void beforeScenario() {
JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation( "target/generated-snippets" );
System.out.println( "jUnitRestDocumentation " +restDocumentation );
spec = new RequestSpecBuilder().addFilter( documentationConfiguration( restDocumentation ) ).build();
System.out.println( "\n spec init .. " +restDocumentation );
}
答案 0 :(得分:3)
您没有使用JUnitRestDocumentation
,因为它打算使用。它被设计用作JUnit规则,这意味着它应该是一个用@Rule
注释的公共字段:
@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
作为规则意味着JUnit将自动为每个测试调用restDocumentation
,允许Spring REST Docs设置和拆除特定于测试的上下文。 NullPointerException
正在发生,因为restDocumentation
尚未以这种方式调用,因此尚未设置上下文。
您尚未描述过如何使用Cucumber,但如果您使用的是JUnit runner,则应该能够通过将restDocumentation
声明为@Rule
来解决问题 - 注释字段如上所示。如果您没有使用其JUnit运行程序,则可能需要使用Spring REST Docs'ManualRestDocumentation
。 Spring REST Docs参考文档包含a section,它描述了在不使用JUnit时如何设置测试。
答案 1 :(得分:3)
我遇到了同样的问题,因为我有多个继承该类的测试类,我在其中声明了JUnitRestDocumentation
实例。我的错误是我使用@Rule
注释声明了规则。我应该使用@ClassRule
并将实例声明为static
。
@ClassRule
public static JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
答案 2 :(得分:1)
它发生在测试 SpockFramework 中,我添加到 pom.xml 中:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-junit4</artifactId>
<scope>test</scope>
</dependency>
答案 3 :(得分:0)
从RestAssured 2.x迁移到RestAssured 3.1.1时,我有相同的症状。
代码库有一种方法可以设置RestAssured,以避免每次测试重复进行仪式:
@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@Before
public void configure_rest_assured() {
RestAssured.port = springServerPort;
RestAssured.config = config().objectMapperConfig(
objectMapperConfig().jackson2ObjectMapperFactory((cls, charset) -> customObjectMapper)
)
...;
RestAssured.requestSpecification = new RequestSpecBuilder()
.addRequestSpecification(documentationConfiguration(docRule, ...))
...
.build();
}
运行良好,直到我迁移到3.x。问题是new RequestSpecBuilder()
会附加自身到默认的静态RestAssured.requestSpecification
。
第一个测试通过了,但是当规则完成后,它被处置(后一部分),当第二个测试开始运行时,Before方法正在链接
以此类推,随着新测试的进行。
但是当第二个测试运行时,RestAssured依次调用规范。数字1,但由于它引用的是已处理规则(beforeOperation在null
上下文中执行)
要解决该代码必须清除以前的规范:
@Before
public void configure_rest_assured() {
RestAssured.port = springServerPort;
RestAssured.config = config().objectMapperConfig(
objectMapperConfig().jackson2ObjectMapperFactory((cls, charset) -> customObjectMapper)
)
...;
RestAssured.requestSpecification = null; // avoid the builder to acquire previous specs.
RestAssured.requestSpecification = new RequestSpecBuilder()
.addRequestSpecification(documentationConfiguration(docRule, ...))
...
.build();
}
答案 4 :(得分:0)
对于将cucumber-java-8
与spring rest文档和spring-security结合使用,以下内容对我有用。
这是从上面结合@AndyWilkison的答案,但使用黄瓜钩子而不是junit规则。
public class StepDefs implements En {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
private ManualRestDocumentation restDocumentation = new ManualRestDocumentation();
public StepDefs() {
BeforeStep((Scenario scenario) -> {
restDocumentation.beforeTest(AuthenticationStepDefs.class, scenario.getName());
mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(springSecurity()).apply(documentationConfiguration(restDocumentation)).build();
});
AfterStep((Scenario scenario) -> {
restDocumentation.afterTest();
});
When("create a rest document for VHR API", () -> {
MvcResult result = mockMvc.perform(/*
your normal call here
*/).
.andDo(document("documentation")).
.andReturn();
}
}
}