Search code examples
javapattern-matchingspring-boot-testmockmvc

Spring MockMVC redirectUrlPattern throws "No Ant-style path pattern"


I've seen this question and this question. I want to match URL pattern so I write my test according to answers in these questions.

@Autowired
private MockMvc mockMvc;

// Ant pattern, example URL: /courses/1/edit
private static final String CREATE_SUCCESS_URL = "/courses/[0-9]+/edit";
// ...
    this.mockMvc.perform(
            post("/courses/create")
                    .with(csrf())
                    .param("name", "New Course"))
            .andExpect(redirectedUrlPattern(CREATE_SUCCESS_URL));

I'm not sure about the right Ant pattern syntax, so I've also tried variations like:

  • CREATE_SUCCESS_URL = "/courses/{[0-9]+}/edit"
  • CREATE_SUCCESS_URL = "/courses/\\d+/edit"
  • CREATE_SUCCESS_URL = "/courses/\\d/edit"
  • CREATE_SUCCESS_URL = "/courses/{\\d+}/edit"
  • CREATE_SUCCESS_URL = "/courses/{id:\\d+}/edit"
  • CREATE_SUCCESS_URL = "/courses/{id:[0-9]+}/edit"

But I always get an exception

java.lang.AssertionError: No Ant-style path pattern
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:36)
    at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:66)
    at org.springframework.test.web.servlet.result.MockMvcResultMatchers.lambda$redirectedUrlPattern$3(MockMvcResultMatchers.java:153)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:195)
    at by.naxa.stackoverflow.CoursesTest.givenNameWhenSubmitCreateCourseThenSuccess(
    ...

One more thing. Pattern CREATE_SUCCESS_URL = "/courses/?/edit" works ok, but I'd like to make sure I match digits only.

Spring Boot version 2.1.2.RELEASE.


Solution

  • A valid Ant path pattern for your requirements would look like:

    CREATE_SUCCESS_URL = "/courses/{[0-9]*}/edit"
    

    or

    CREATE_SUCCESS_URL = "/courses/{\\d*}/edit"
    

    This AssertionError is caused by the following method inside org.springframework.util.AntPathMatcher:

    public boolean isPattern(String path) {
        return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
    }
    

    So any string containing * or ? will work.