1

I would like to test that when an unknown url is requested and a 404 error is generated that my web app actually redirects to the right place.

I havent been able to get this working, I think because tomcat is handling the 404 errors so the forwardedUrl is always null for the tests. I know this works in reality because if I enter some rubbish into the url my app does redirect to my custom page.

My unit test looks like:

@Test
public void testUnknownUrl() throws Exception {
mockMvc.perform(get("/url_doesnt_exist"))
    .andExpect(status().isNotFound())        
    .andExpect(forwardedUrl("/static/error/Sorry.html"));             
}

My web.xml configuration is:

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<error-page>
    <error-code>404</error-code>
    <location>/static/error/Sorry.html</location>
</error-page>

The mapping for /static is defined in my spring config like:

<resources mapping="/static/**" location="/resources/" />

Ultimately I would like to mock a request to an unknown url and then check that the page being returned is /static/error/Sorry.html.

Am I doing something wrong or is this not the way to handle 404 etc in spring? The check of the forwarded url in the unit test is always null.

A slightly different question but related all the same is, at what point does the tomcat error handling get invoked over and above the spring controller advice handling?

4

2 回答 2

1

I'm not sure about the configuration with the /static path in your web.xml, it shouldn't be like that depending on your dispatcher-servlet (default name) configuration; but as far as I can tell you are in the right path.

This is what I have for mine:

@WebAppConfiguration
@ActiveProfiles("development")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class ErrorControllerTest {
  @Autowired
  private WebApplicationContext context;
  private MockMvc mockMvc;

  @Before
  public void setUp() {
    mockMvc = MockMvcBuilders.webAppContextSetup(context)/*.alwaysExpect(status().isOk())*/.build();
  }

  @Test
  public void testError() throws Exception {
    mockMvc.perform(get("/error").contentType(MediaType.TEXT_HTML))
        .andExpect(status().isOk()) // See "alwaysExpect" above
        .andExpect(view().name("error"))
        .andExpect(forwardedUrl("/WEB-INF/views/error.jsp"));
  }

  @Test
  public void testResourceNotFound() throws Exception {
    mockMvc.perform(get("/resource-not-found").contentType(MediaType.TEXT_HTML))
        .andExpect(status().isNotFound())
        .andExpect(view().name("resource-not-found"))
        .andExpect(forwardedUrl("/WEB-INF/views/resource-not-found.jsp"));
  }
}

Sample project is here. I'm using JSPs but you can switch to .html just by changing the InternalResourceViewResolver configuration.

于 2015-08-17T14:19:58.773 回答
0

I am using spring 3 and after some reading around I have found out the dispatcher servlet just returns a response code without throwing an exception which I guess is why tomcat always handles this.

Removing the error page tags from web.xml results in a tomcat generic 404 page, so I think the answer to this is to upgrade to spring 4 where I can then pass an init param to the dispatcher servlet requesting it throw an error for a page not found.

I am happy to be corrected on this though as it may help my understanding.

于 2015-08-18T08:28:12.307 回答