今天在办公室开始学习Spring Test MVC框架,它看起来很方便,但是直接面对一些严重的麻烦。花了几个小时谷歌搜索,但找不到与我的问题有关的任何事情。
这是我非常简单的测试类:
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = WebAppContext.class)
public class ControllerTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = webAppContextSetup(wac).build();
}
@Test
public void processFetchErrands() throws Exception {
mockMvc.perform(post("/errands.do?fetchErrands=true"))
.andExpect(status().isOk())
.andExpect(model().attribute("errandsModel", allOf(
hasProperty("errandsFetched", is(true)),
hasProperty("showReminder", is(false)))));
}
}
测试到达以下控制器,但由于未经正确授权,因此在第一个if
子句上失败。
@RequestMapping(method = RequestMethod.POST, params="fetchErrands")
public String processHaeAsioinnit(HttpSession session, HttpServletRequest request, ModelMap modelMap,
@ModelAttribute(ATTR_NAME_MODEL) @Valid ErrandsModel model,
BindingResult result, JopoContext ctx) {
if (request.isUserInRole(Authority.ERRANDS.getCode())) {
return Page.NO_AUTHORITY.getCode();
}
[...]
}
如何为MockHttpServletRequest
创建的MockMvcRequestBuilders.post()
添加用户角色,以便我可以通过我的控制器上的权限检查?
我知道MockHttpServletRequest
有一个方法addUserRole(String role)
,但由于MockMvcRequestBuilders.post()
返回MockHttpServletRequestBuilder
,我永远不会抓住MockHttpServletRequest
因此无法调用那种方法。
检查Spring源代码,MockHttpServletRequestBuilder
没有与用户角色相关的方法,也没有在该类中调用MockHttpServletRequest.addUserRole(String role)
,所以我不知道如何告诉它将用户角色添加到请求。
我能想到的是添加一个自定义过滤器来过滤链并从那里调用自定义HttpServletRequestWrapper
,提供isUserInRole()
的实现,但对于这种情况,这似乎有点极端。当然,框架应该提供更实用的东西吗?
答案 0 :(得分:8)
我想我找到了easier way
@Test
@WithMockUser(username = "username", roles={"ADMIN"})
public void testGetMarkupAgent() throws Exception {
mockMvc.perform(get("/myurl"))
.andExpect([...]);
}
您可能需要以下maven条目
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>4.0.4.RELEASE</version>
<scope>test</scope>
</dependency>
答案 1 :(得分:2)
Spring MVC Test具有principal()方法,允许模拟这样的情况的请求凭证。这是一个测试的示例,其中设置了一些模拟凭证:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath:spring/mvc-dispatcher-servlet.xml")
public class MobileGatewayControllerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@Autowired
private Principal principal;
@Autowired
private MockServletContext servletContext;
@Before
public void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void testExampleRequest() throws Exception {
servletContext.declareRoles("ROLE_1");
mockMvc.perform(get("/testjunit")
.accept(MediaType.APPLICATION_JSON)
.principal(principal))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.[1]").value("test"));
}
}
这是如何创建模拟主体的示例:
@Configuration
public class SetupTestConfig {
@Bean
public Principal createMockPrincipal() {
Principal principal = Mockito.mock(Principal.class);
Mockito.when(principal.getName()).thenReturn("admin");
return principal;
}
}
答案 2 :(得分:1)
您可以在请求中使用RequestPostProcessor之前注入MockHttpServletRequest。
deleteClickedEvent
答案 3 :(得分:1)
还有一种简单的替代方法可以为单个请求设置特定的用户角色。如果您只想以授权用户的身份执行单个操作(例如设置测试装置),然后检查具有不同角色的用户是否可以执行某些操作,则可能会很方便:
ResultActions registerNewUserAsAdmin(String username, String password) throws Exception {
final SignUpRequest signUpPayload = new SignUpRequest(username, password);
final MockHttpServletRequestBuilder registerUserRequest = post(SIGN_UP_URL)
.with(user("admin").roles("ADMIN"))
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(jsonMapper.writeValueAsString(signUpPayload));
return mockMvc.perform(registerUserRequest);
}
有关更多详细信息,请参见SecurityMockMvcRequestPostProcessors。
答案 4 :(得分:0)
如果您使用的是权限而不是角色,则在请求中授予权限,如下所示。
mockMvc.perform(
put(REQUEST_URL).param(PARM, VALUE)
.with(SecurityMockMvcRequestPostProcessors.user(USERNAME).authorities(new SimpleGrantedAuthority("ADMIN")))
.contentType(APPLICATION_FORM_URLENCODED)
)