Search code examples
springjunitmockmvcparameterized

Use MockMvc With Junit Parameterized tests


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)

Solution

  • 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);
            }
        }
    }