I'm trying to test my project using BDD and therefore im using Cucumber. The problem is, that when I want to test ProductController i can't properly mock my ProductService and i get NullPointerException - my service is null. Below is code for my steps.
@SpringBootTest
@AutoConfigureMockMvc
public class ProductControllerSteps {
long productId;
Product product;
@Autowired
MockMvc mockMvc;
@MockBean
ProductService service;
private ResultActions result;
@Given("user has a valid product id")
public void user_has_a_valid_product_id() {
productId = 1L;
product = new Product();
product.setId(productId);
Mockito.when(service.getProductById(productId)).thenReturn(product);
}
@When("user makes GET request")
public void user_makes_get_request() throws Exception {
result = mockMvc.perform(MockMvcRequestBuilders.get("/api/products/"+productId).accept(MediaType.APPLICATION_JSON_VALUE)).andDo(print());
}
@Then("system returns product data")
public void system_returns_product_data() throws Exception {
result.andExpect(status().is2xxSuccessful());
}
}
As i seen in cucumber guides i also created such a classes for cucumber configuration:
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
public class RunCucumberTest {
}
and also:
@CucumberContextConfiguration
@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = ShopApiApplication.class)
public class SpringGlue{
}
I'm trying to mock my service with mockito, yet every kind of configuration does not work and result in null pointer exception, i dont have any idea how to make it work.
The class annotated with @CucumberContextConfiguration
is used to configure the Spring application context using Springs Test Context Framework Manager. This includes setting up mocks through the MockitoTestExecutionListener
.
Declaring a mock bean can be done with an annoatation on the SpringGlue
class. It is also possible to declare mocks by adding fields to the class and annotating those.
@CucumberContextConfiguration
@SpringBootTest
@AutoConfigureMockMvc
@ContextConfiguration(classes = ShopApiApplication.class)
@MockBean(ProductService.class)
public class SpringGlue {
}
And because of that the MockBean
annotation on the ProductControllerSteps
does not do anything. This class should look like:
public class ProductControllerSteps {
...
@Autowired
MockMvc mockMvc;
@Autowired
ProductService service;
The autowired service will be a mock so you can use Mockito.when(...)
as normal.
Note: If you have multiple features they'll all use the same context configuration. If you need multiple configurations, multiple runners are needed with different glue configurations.