带有模式的Spring MockMvc redirectedUrl [英] Spring MockMvc redirectedUrl with pattern

查看:114
本文介绍了带有模式的Spring MockMvc redirectedUrl的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的PersonController类,提供了save()方法来持久保存来自http post请求的对象.

package org.rw.controller;

import java.sql.Timestamp;
import java.util.List;

import org.rw.entity.Person;
import org.rw.service.PersonService;
import org.rw.spring.propertyeditor.TimestampPropertyEditor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
@RequestMapping(value="/person")
public class PersonController {

    private static final Logger logger = LoggerFactory.getLogger(PersonController.class);

    @Autowired
    private PersonService personService;

    @Autowired
    TimestampPropertyEditor timestampPropertyEditor;


    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Timestamp.class, "dob", timestampPropertyEditor);
    }


    @RequestMapping(value="/save", method=RequestMethod.POST)
    public String save(Model model, Person person) {
        Long personId = personService.save(person);
        return "redirect:view/" + personId;
    }

}

由于save()方法返回为return "redirect:view/" + personId;.每个请求都会有所不同.

 mockMvc.perform(
    post("/person/save", new Object[0])
        .param("firstName", "JunitFN")
        .param("lastName", "JunitLN")
        .param("gender", "M")
        .param("dob", "11/02/1989")
 ).andExpect(
        redirectedUrlPattern("view/[0-9]+")
 );

"view/6"可能取决于持久对象的ID.

然后我有一个简单的类,可以通过弹簧模拟来测试上述控制器.

package org.rw.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.rw.service.UserService;
import org.rw.test.SpringControllerTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class PersonControllerTest extends SpringControllerTest {


    @Autowired
    private UserService userService;


    @Test
    public void add() throws Exception {
        mockMvc.perform(get("/person/add", new Object[0])).andExpect(status().isOk());
    }


    @Test
    public void save() throws Exception {
        UserDetails userDetails = userService.findByUsername("anil");
        Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authToken);

        mockMvc.perform(
            post("/person/save", new Object[0])
                .param("firstName", "JunitFN")
                .param("lastName", "JunitLN")
                .param("gender", "M")
                .param("dob", "11/02/1989")
        ).andExpect(
                redirectedUrl("view")
        );
    }


}

现在在这里我有一个问题,redirectedUrl("view")拒绝值"view/5".我已经尝试过redirectedUrl("view*")redirectedUrl("view/*"),但是它不起作用.


在这里,我有下面的解决方法

MvcResult result = mockMvc.perform(
    post("/person/save", new Object[0])
        .param("firstName", "JunitFN")
        .param("lastName", "JunitLN")
        .param("gender", "MALE")
        .param("dob", "11/02/1989")
).andExpect(
        //redirectedUrl("view")
        status().isMovedTemporarily()
).andReturn();

MockHttpServletResponse response = result.getResponse();

String location = response.getHeader("Location");

Pattern pattern = Pattern.compile("\\Aview/[0-9]+\\z");
assertTrue(pattern.matcher(location).find());

但我仍在寻找正确的方法.


更新:

我在春天吉拉这里发布了相同的问题:

解决方案

从Spring 4.0开始,您可以使用 Paulius Matulionis

从3.x版本开始,此功能尚不支持,但是您可以轻松添加自定义结果匹配器

private static ResultMatcher redirectedUrlPattern(final String expectedUrlPattern) {
    return new ResultMatcher() {
        public void match(MvcResult result) {
            Pattern pattern = Pattern.compile("\\A" + expectedUrlPattern + "\\z");
            assertTrue(pattern.matcher(result.getResponse().getRedirectedUrl()).find());
        }
    };
}

并像内置匹配器一样使用它

 mockMvc.perform(
    post("/person/save", new Object[0])
        .param("firstName", "JunitFN")
        .param("lastName", "JunitLN")
        .param("gender", "M")
        .param("dob", "11/02/1989")
 ).andExpect(
        redirectedUrlPattern("view/[0-9]+")
 );

I have a simple PersonController class that provides save() method to persist the object from http post request.

package org.rw.controller;

import java.sql.Timestamp;
import java.util.List;

import org.rw.entity.Person;
import org.rw.service.PersonService;
import org.rw.spring.propertyeditor.TimestampPropertyEditor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
@RequestMapping(value="/person")
public class PersonController {

    private static final Logger logger = LoggerFactory.getLogger(PersonController.class);

    @Autowired
    private PersonService personService;

    @Autowired
    TimestampPropertyEditor timestampPropertyEditor;


    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Timestamp.class, "dob", timestampPropertyEditor);
    }


    @RequestMapping(value="/save", method=RequestMethod.POST)
    public String save(Model model, Person person) {
        Long personId = personService.save(person);
        return "redirect:view/" + personId;
    }

}

As the save() method returns as return "redirect:view/" + personId;. It will be diffrerent for every request. it may be like "view/5" or "view/6" depending on the id of the object that has been persisted.

Then i have a simple class to test the above controller with spring mocking.

package org.rw.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.rw.service.UserService;
import org.rw.test.SpringControllerTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class PersonControllerTest extends SpringControllerTest {


    @Autowired
    private UserService userService;


    @Test
    public void add() throws Exception {
        mockMvc.perform(get("/person/add", new Object[0])).andExpect(status().isOk());
    }


    @Test
    public void save() throws Exception {
        UserDetails userDetails = userService.findByUsername("anil");
        Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authToken);

        mockMvc.perform(
            post("/person/save", new Object[0])
                .param("firstName", "JunitFN")
                .param("lastName", "JunitLN")
                .param("gender", "M")
                .param("dob", "11/02/1989")
        ).andExpect(
                redirectedUrl("view")
        );
    }


}

now here i have a problem that redirectedUrl("view") is rejecting value "view/5". I have tried redirectedUrl("view*") and redirectedUrl("view/*") but its not working.


Edit :

Here I have got a workaround as per below

MvcResult result = mockMvc.perform(
    post("/person/save", new Object[0])
        .param("firstName", "JunitFN")
        .param("lastName", "JunitLN")
        .param("gender", "MALE")
        .param("dob", "11/02/1989")
).andExpect(
        //redirectedUrl("view")
        status().isMovedTemporarily()
).andReturn();

MockHttpServletResponse response = result.getResponse();

String location = response.getHeader("Location");

Pattern pattern = Pattern.compile("\\Aview/[0-9]+\\z");
assertTrue(pattern.matcher(location).find());

but still i am looking for the proper way.


update:

I have posted the same issue on spring jira here :

解决方案

Since spring 4.0 you can use redirectedUrlPattern as pointed by Paulius Matulionis

As of spring 3.x this is not supported out of the box but you can easily add you custom result matcher

private static ResultMatcher redirectedUrlPattern(final String expectedUrlPattern) {
    return new ResultMatcher() {
        public void match(MvcResult result) {
            Pattern pattern = Pattern.compile("\\A" + expectedUrlPattern + "\\z");
            assertTrue(pattern.matcher(result.getResponse().getRedirectedUrl()).find());
        }
    };
}

And use it like build-in matcher

 mockMvc.perform(
    post("/person/save", new Object[0])
        .param("firstName", "JunitFN")
        .param("lastName", "JunitLN")
        .param("gender", "M")
        .param("dob", "11/02/1989")
 ).andExpect(
        redirectedUrlPattern("view/[0-9]+")
 );

这篇关于带有模式的Spring MockMvc redirectedUrl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆