Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Spring3.2新mvc测试登录用户_Java_Spring_Spring Mvc_Junit - Fatal编程技术网

Java 如何使用Spring3.2新mvc测试登录用户

Java 如何使用Spring3.2新mvc测试登录用户,java,spring,spring-mvc,junit,Java,Spring,Spring Mvc,Junit,在我必须测试需要登录用户的服务之前,这一切都很正常。如何将用户添加到上下文: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext-test.xml") @WebAppConfiguration public class FooTest { @Autowired private WebApplicationContext webApplicationContext;

在我必须测试需要登录用户的服务之前,这一切都很正常。如何将用户添加到上下文:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-test.xml")
@WebAppConfiguration
public class FooTest {
@Autowired
private WebApplicationContext webApplicationContext;

private MockMvc mockMvc;

@Resource(name = "aService")
private AService aService; //uses logged in user

@Before
public void setup() {
    this.mockMvc = webAppContextSetup(this.webApplicationContext).build();
}

您应该能够将用户添加到安全上下文中:

List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
list.add(new GrantedAuthorityImpl("ROLE_USER"));        
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password,list);
SecurityContextHolder.getContext().setAuthentication(auth);
List List=new ArrayList();
添加(新的授权机构impl(“角色用户”);
UsernamePasswordAuthenticationToken auth=新的UsernamePasswordAuthenticationToken(用户、密码、列表);
SecurityContextHolder.getContext().setAuthentication(auth);

如果要在最新的spring安全测试包中使用MockMVC,请尝试以下代码:

Principal principal = new Principal() {
        @Override
        public String getName() {
            return "TEST_PRINCIPAL";
        }
    };
getMockMvc().perform(get("http://your-url.com").principal(principal))
        .andExpect(status().isOk()));

请记住,您必须使用基于主体的身份验证才能工作。

如果成功的身份验证生成一些cookie,则您可以捕获该cookie(或仅捕获所有cookie),并在接下来的测试中传递该cookie:

@Autowired
private WebApplicationContext wac;

@Autowired
private FilterChainProxy filterChain;

private MockMvc mockMvc;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
      .addFilter(filterChain).build();
}

@Test
public void testSession() throws Exception {
    // Login and save the cookie
    MvcResult result = mockMvc.perform(post("/session")
      .param("username", "john").param("password", "s3cr3t")).andReturn();
    Cookie c = result.getResponse().getCookie("my-cookie");
    assertThat(c.getValue().length(), greaterThan(10));

    // No cookie; 401 Unauthorized
    mockMvc.perform(get("/personal").andExpect(status().isUnauthorized());

    // With cookie; 200 OK
    mockMvc.perform(get("/personal").cookie(c)).andExpect(status().isOk());

    // Logout, and ensure we're told to wipe the cookie
    result = mockMvc.perform(delete("/session").andReturn();
    c = result.getResponse().getCookie("my-cookie");
    assertThat(c.getValue().length(), is(0));
}
虽然我知道我没有在这里发出任何HTTP请求,但我有点喜欢上面的集成测试和我的控制器以及Spring安全实现之间更严格的分离

为了使代码不那么冗长,我在发出每个请求后使用以下方法合并cookie,然后在每个后续请求中传递这些cookie:

/**
 * Merges the (optional) existing array of Cookies with the response in the
 * given MockMvc ResultActions.
 * <p>
 * This only adds or deletes cookies. Officially, we should expire old
 * cookies. But we don't keep track of when they were created, and this is
 * not currently required in our tests.
 */
protected static Cookie[] updateCookies(final Cookie[] current,
  final ResultActions result) {

    final Map<String, Cookie> currentCookies = new HashMap<>();
    if (current != null) {
        for (Cookie c : current) {
            currentCookies.put(c.getName(), c);
        }
    }

    final Cookie[] newCookies = result.andReturn().getResponse().getCookies();
    for (Cookie newCookie : newCookies) {
        if (StringUtils.isBlank(newCookie.getValue())) {
            // An empty value implies we're told to delete the cookie
            currentCookies.remove(newCookie.getName());
        } else {
            // Add, or replace:
            currentCookies.put(newCookie.getName(), newCookie);
        }
    }

    return currentCookies.values().toArray(new Cookie[currentCookies.size()]);
}
…最终:

Cookie[] cookies = initCookies();

ResultActions actions = mockMvc.perform(get("/personal").cookie(cookies)
  .andExpect(status().isUnauthorized());
cookies = updateCookies(cookies, actions);

actions = mockMvc.perform(post("/session").cookie(cookies)
  .param("username", "john").param("password", "s3cr3t"));
cookies = updateCookies(cookies, actions);

actions = mockMvc.perform(get("/personal").cookie(cookies))
  .andExpect(status().isOk());
cookies = updateCookies(cookies, actions);

为什么校长的解决方案对我不起作用,因此,我想提出另一种解决方法:

mockMvc.perform(get("your/url/{id}", 5).with(user("anyUserName")))

对于Spring4,此解决方案使用会话而不是cookie模拟formLogin和logout,因为spring安全测试不返回cookie

因为继承测试不是最佳做法,所以可以在测试中@Autowire该组件并调用其方法

使用此解决方案,如果您在测试结束时调用了
performLogin
,则在
mockMvc
上执行的每个操作都将被称为已验证

import org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.mock.web.MockHttpServletRequest;
导入org.springframework.mock.web.MockHttpSession;
导入org.springframework.stereotype.Component;
导入org.springframework.test.web.servlet.MockMvc;
导入org.springframework.test.web.servlet.ResultActions;
导入org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
导入org.springframework.test.web.servlet.setup.MockMvcBuilders;
导入org.springframework.web.context.WebApplicationContext;
导入javax.servlet.Filter;
导入静态com.condix.SessionLogoutRequestBuilder.sessionLogout;

导入静态org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
导入静态org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
导入静态org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated;
导入静态org.springframework.security.test.web.servlet.setup.SecurityMockMVCConfiguers.springSecurity;
导入静态org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
导入静态org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
导入静态org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @组成部分 公共类SessionBasedMockMvc{ 私有静态最终字符串HOME_PATH=“/”; 私有静态最终字符串LOGOUT_PATH=“/login?LOGOUT”; @自动连线 私有WebApplicationContext WebApplicationContext; @自动连线 私有过滤器springSecurityFilterChain; 私有MockMvc-MockMvc; 公共MockMvc createSessionBasedMockMvc(){ 最终MockHttpServletRequestBuilder defaultRequestBuilder=get(“/dummy path”); this.mockMvc=MockMvcBuilders.webAppContextSetup(this.webApplicationContext) .defaultRequest(defaultRequestBuilder) .alwaysDo(结果->setSessionBackOnRequestBuilder(defaultRequestBuilder,result.getRequest()) .apply(springSecurity(springSecurityFilterChain)) .build(); 返回此.mockMvc; } public void performLogin(最终字符串用户名、最终字符串密码)引发异常{ final ResultActions ResultActions=this.mockMvc.perform(formLogin().user(username).password(password)); 此.assertSuccessLogin(resultActions); } public void performLogout()引发异常{ final ResultActions ResultActions=this.mockMvc.perform(sessionLogout()); 此.assertSuccessLogout(结果); } 私有MockHttpServletRequestSetSessionBackOnRequestBuilder(最终MockHttpServletRequestBuilder requestBuilder, 最终MockHttpServletRequest(请求){ session((MockHttpSession)request.getSession()); 返回请求; } 私有void assertSuccessLogin(最终结果ResultActions ResultActions)引发异常{ resultActions.andExpect(状态().isFound()) .andExpect(已验证() .andExpect(重定向到URL(主路径)); } 私有void资产成功注销(最终结果ResultActions ResultActions)引发异常{ resultActions.andExpect(状态().isFound()) .andExpect(未经身份验证的()) .andExpect(重定向到URL(注销路径)); } }
因为默认的
LogoutRequestBuilder
不支持会话,我们需要创建另一个注销请求生成器

import org.springframework.beans.Mergeable;
导入org.springframework.mock.web.MockHttpServletRequest;
导入org.springframework.mock.web.MockHttpSession;
导入org.springframework.test.util.ReflectionTestUtils;
导入org.springframework.test.web.servlet.request.configurableMartRequestBuilder;
导入org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
导入org.springframework.test.web.servlet.request.RequestPostProcessor;
导入org.springframework.util.Assert;
导入org.springframework.util.StringUtils;
导入javax.ser
mockMvc.perform(get("your/url/{id}", 5).with(user("anyUserName")))
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners(listeners={ServletTestExecutionListener.class,
    DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    WithSecurityContextTestExcecutionListener.class})
@WithMockUser
public class WithMockUserTests {
    ...
}