I am testing with Spring Boot (3.3.0) and Cucumber (7.18.0). I have a repository which I want to mock and I have included the necessary (I think) configuration for Spring and Cucumber but I get "java.lang.NullPointerException: Cannot invoke "com.example.sampleproject.repository.ArtistRepository.findById(Object)" because "this.artistRepository" is null".
Here is my step def class:
@SpringBootTest
@ContextConfiguration(classes = {SampleProjectApplication.class, CucumberSpringConfiguration.class})
public class FindArtistByIdStepDefs {
@MockBean
private ArtistRepository artistRepository;
private DataLoaderService dataLoaderService;
private List<ArtistEntity> mockedArtists = new ArrayList<>();
private List<AlbumEntity> mockedAlbums = new ArrayList<>();
public FindArtistByIdStepDefs(DataLoaderService dataLoaderService) {
this.dataLoaderService = dataLoaderService;
}
@Given("artists exist in the DB")
public void theFollowingArtistsExistInTheDB(DataTable dataTable) {
List<Map<String, String>> map = dataTable.asMaps(String.class, String.class);
for (Map<String, String> row : map) {
ArtistEntity artist = new ArtistEntity();
String name = row.get("name");
String description = row.get("description");
long id = Long.parseLong(row.get("id"));
artist.setArtist(name);
artist.setDescription(description);
artist.setId(id);
mockedArtists.add(artist);
Mockito.when(artistRepository.findById(artist.getId())).thenReturn(Optional.of(artist));
}
Then I have CucumberSpring config:
@CucumberContextConfiguration
@SpringBootTest(classes = SampleProjectApplication.class)
public class CucumberSpringConfiguration {
public CucumberSpringConfiguration() {
System.out.println("CucumberSpringConfiguration initialized");
}
}
Test Runner:
@Suite
@SelectClasspathResource("features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.sampleproject.steps, com.example.sampleproject.config")
public class TestRunner {
}
When I add @CucumberContextConfiguration on the FindArtistByIdStepDefs class and remove the other it works. But I want this configuration to be more centralized since I have another step def class and plan to have more.
What might be causing @MockBean to result in a NullPointerException when using a centralized configuration? How can I ensure that the MockBean is properly injected while keeping a centralized configuration?
Your step definition class should look like this.
public class FindArtistByIdStepDefs {
private final ArtistRepository artistRepository;
private final DataLoaderService dataLoaderService;
private List<ArtistEntity> mockedArtists = new ArrayList<>();
private List<AlbumEntity> mockedAlbums = new ArrayList<>();
public FindArtistByIdStepDefs(
DataLoaderService dataLoaderService,
ArtistRepository artistRepository
) {
this.dataLoaderService = dataLoaderService;
this.artistRepository = artistRepository;
}
...
And your context configuration should like this:
@CucumberContextConfiguration
@SpringBootTest(classes = SampleProjectApplication.class)
public class CucumberSpringConfiguration {
@MockBean
private ArtistRepository artistRepository;
}
By declaring the ArtistRepository
as MockBean
the mocks will be injected in the FindArtistByIdStepDefs
. You can then use mockito as you would normally.
Additionally both CucumberSpringConfiguration
and FindArtistByIdStepDefs
should be on the glue path. If they're in the same package, they probably are.