我需要用很多测试用例来测试 API。因此,我决定使用 Junit 参数化测试。
但是我无法运行我的测试,因为 MockMvc 不自动配置并且它是空的。
这是我的测试课:
@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));
}
}
在这堂课上我写了我的测试用例:
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);
}
}
}
当我尝试运行测试时遇到此异常:
java.lang.NullPointerException: Cannot invoke "org.springframework.test.web.servlet.MockMvc.perform(org.springframework.test.web.servlet.RequestBuilder)" because "this.mockMvc" is null
我也尝试自己实例化 MockMvc 但出现异常:
@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();
}
.
.
.
例外:
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)
作为M。 Deinum 在评论中建议,问题是使用 JUnit4 而不是 JUnit5。
因此,我决定为有相同问题的任何人发布一个包含此问题解决方案的答案。
这就是我的测试类现在的样子:
@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));
}
}
以及测试用例提供者类:
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);
}
}
}