Reputation: 81
I am trying to test spring rest documentation for rest API for our services using spring cucumber jvm but end up with a null pointer exeception when I try to execute the scenario, as the framework is not able to intialize the Junit context.
Error Message:
java.lang.NullPointerException at
org.springframework.restdocs.ManualRestDocumentation.beforeOperation(ManualRestDocumentation.java:90) at
org.springframework.restdocs.JUnitRestDocumentation.beforeOperation(JUnitRestDocumentation.java:76)
Code:
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 );
}
Step definition code:
@Given("^create a rest document for VHR API$")
public void create_a_rest_document_for_VHR_API() throws Throwable {
estAssured.given( spec )
.accept( "application/json" )
.filter( document( "vhrdocument" ) ) .when()
.get( props.getVhrrequesturl() + "/vhrData/{vehicleID}", "5VW4T7AU0FM029999" ) .then().log().all();
}
Upvotes: 3
Views: 1286
Reputation: 2858
it happened with test SpockFramework, and i added to pom.xml:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-junit4</artifactId>
<scope>test</scope>
</dependency>
Upvotes: 2
Reputation: 7047
For using cucumber-java-8
with spring rest docs and spring-security the following worked for me.
This is combining @AndyWilkison's answer from above but using the cucumber hooks instead of junit rules.
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();
}
}
}
Upvotes: 0
Reputation: 42223
I had the same symptoms when migrating from RestAssured 2.x to RestAssured 3.1.1.
The codebase had a way to setup RestAssured in order to avoid repetitive ceremony for every tests :
@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();
}
This was working well, until I migrated to 3.x. The issue was that new RequestSpecBuilder()
will append itself to the default static RestAssured.requestSpecification
.
The first test passed, but when it finished the rule was disposed (the after part), when the second test started to ran, the Before method was chaining
And so on as new tests are ran.
But when the second test is run RestAssured invoke specification in order, e.g. the number 1, but since it was referencing a disposed rule (the beforeOperation was executed on a null
context)
To fix that the code had to clear the previous specifications :
@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();
}
Upvotes: 0
Reputation: 4000
I had the same problem because I had multiple test class inheriting the class, in which I declared the JUnitRestDocumentation
instance. My mistake was that I declared the rule using the @Rule
annotation. I should have used @ClassRule
and declared the instance as static
.
@ClassRule
public static JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
Upvotes: 4
Reputation: 116051
You aren't using JUnitRestDocumentation
as it's intended to be used. It's designed to be used as a JUnit rule which means it should be a public field annotated with @Rule
:
@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
Being a rule means that JUnit will automatically call restDocumentation
for each test, allowing Spring REST Docs to set up and tear down the test-specific context. The NullPointerException
is occurring because restDocumentation
hasn't been called in this way and, therefore, the context hasn't been set up.
You haven't described how you're using Cucumber, but if you're using it's JUnit runner you should be able to fix the problem by declaring restDocumentation
as a @Rule
-annotated field as shown above. If you're not using its JUnit runner, you may need to use Spring REST Docs' ManualRestDocumentation
instead. The Spring REST Docs reference documentation contains a section that describes how to set up your tests when you're not using JUnit.
Upvotes: 4