java 带有模式的 Spring MockMvc redirectedUrl

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17834034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 15:09:50  来源:igfitidea点击:

Spring MockMvc redirectedUrl with pattern

javaspringjunitmocking

提问by Anil Bharadia

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

我有一个简单的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;
    }

}

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.

由于该save()方法返回为return "redirect:view/" + personId;. 每个请求都会有所不同。它可能类似于"view/5""view/6"取决于已持久化的对象的 id。

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

然后我有一个简单的类来使用 spring 模拟测试上述控制器。

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.

现在我有一个redirectedUrl("view")拒绝 value的问题"view/5"。我试过了redirectedUrl("view*")redirectedUrl("view/*")但它不起作用。



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:

我在spring jira上发布了同样的问题:

回答by Roman Konoval

Since spring 4.0 you can use redirectedUrlPatternas pointed by Paulius Matulionis

由于弹簧4.0可以使用redirectedUrlPattern由尖的Paulius Matulionis

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

从 spring 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());
        }
    };
}

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]+")
 );

回答by Paulius Matulionis

Since 4.0it is available in Spring itself.

因为4.0它在 Spring 本身中可用。

Please check here.

请检查这里