I need to test APIs with so many test cases. Because of that I deceided to use Junit Parameterized tests.
But I could'nt run my test, because MockMvc does'nt autowierd and it's null.
This is my test class:
@RunWith(Parameterized.class)
@AutoConfigureMockMvc
@SpringBootTest
public class BadgeControllerIT {
@Resource
private MockMvc mockMvc;
private final MultiValueMap<String, String> params;
private final String expectedBadgeAsSVG;
private final ResultMatcher status;
public BadgeControllerIT(final MultiValueMap<String, String> params,
final String expectedBadgeAsSVG,
final ResultMatcher status) {
this.params = params;
this.expectedBadgeAsSVG = expectedBadgeAsSVG;
this.status = status;
}
@Parameterized.Parameters
public static Collection<Object[]> parameters() {
return Arrays.asList(BadgeControllerTestsInputProvider.TEST_INPUTS);
}
@Test
public void badgeControllerTests() throws Exception {
mockMvc
.perform(
get("/api/badge")
.queryParams(params)
.accept("image/svg+xml")
)
.andExpect(status)
.andExpect(content().string(expectedBadgeAsSVG));
}
}
And in this class i wrote my test cases:
public class BadgeControllerTestsInputProvider {
public final static Object[][] TEST_INPUTS = new Object[][]{
{
new LinkedMultiValueMap<String, String>(),
readBadge("some-badge"),
status().isOk()
}
};
private static String readBadge(String badge) {
try {
final File svgFile = ResourceUtils.getFile("classpath:testdata/" + badge + ".svg");
return FileUtils.readFileToString(svgFile, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
When I try to run the test I encounter this exception:
java.lang.NullPointerException: Cannot invoke "org.springframework.test.web.servlet.MockMvc.perform(org.springframework.test.web.servlet.RequestBuilder)" because "this.mockMvc" is null
I also tried to Instantiate the MockMvc by myself but I got exception:
@RunWith(Parameterized.class)
@WebAppConfiguration
@SpringBootTest
public class BadgeControllerIT {
@Resource
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}
.
.
.
The exception:
java.lang.IllegalArgumentException: WebApplicationContext is required
at org.springframework.util.Assert.notNull(Assert.java:201)
at org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder.<init>(DefaultMockMvcBuilder.java:52)
at org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup(MockMvcBuilders.java:51)
As M. Deinum suggested in the comment, the problem was using JUnit4 instead of JUnit5.
So I decided to post an answer with the solution to this problem for anyone with the same issue.
this is how my test class looks now:
@AutoConfigureMockMvc
@SpringBootTest
public class BadgeControllerIT {
@Resource
private MockMvc mockMvc;
@ParameterizedTest
@ArgumentsSource(BadgeControllerTestsArgumentProvider.class)
public void badgeControllerTests(MultiValueMap<String, String> params, String expectedBadgeAsSVG, ResultMatcher status) throws Exception {
mockMvc
.perform(
get("/api/badge")
.queryParams(params)
.accept("image/svg+xml")
)
.andExpect(status)
.andExpect(content().string(expectedBadgeAsSVG));
}
}
And the test case provider class:
public class BadgeControllerTestsArgumentProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
return Stream.of(
Arguments.of(
new LinkedMultiValueMap<String, String>(),
readBadge("1"),
status().isOk()
)
);
}
private static String readBadge(String badge) {
try {
final File svgFile = ResourceUtils.getFile("classpath:testdata/" + badge + ".svg");
return FileUtils.readFileToString(svgFile, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}