Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.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
Spring 模拟SecurityContextHolder/验证始终返回null_Spring_Spring Security_Mockito_Junit4_Spring Test - Fatal编程技术网

Spring 模拟SecurityContextHolder/验证始终返回null

Spring 模拟SecurityContextHolder/验证始终返回null,spring,spring-security,mockito,junit4,spring-test,Spring,Spring Security,Mockito,Junit4,Spring Test,我知道这个问题被问了很多,但也许我有一些特别的问题。我正在尝试对支持REST(而不是Spring MVC)的Spring引导应用程序进行一些集成测试,并且出于某种原因,SecurityContextHolder.getContext().getAuthentication()始终返回null,即使在测试中使用@WithMockUser。我不确定这是否与在配置类上使用概要文件有关,但到目前为止,我们还没有遇到过这方面的问题 等级 附加说明:这个Spring Boot应用程序也使用OAuth2进行授

我知道这个问题被问了很多,但也许我有一些特别的问题。我正在尝试对支持REST(而不是Spring MVC)的Spring引导应用程序进行一些集成测试,并且出于某种原因,
SecurityContextHolder.getContext().getAuthentication()
始终返回null,即使在测试中使用
@WithMockUser
。我不确定这是否与在配置类上使用概要文件有关,但到目前为止,我们还没有遇到过这方面的问题

等级 附加说明:这个Spring Boot应用程序也使用OAuth2进行授权,但在这些测试中必须关闭它。这就是为什么我们使用配置文件。省略
@ActiveProfiles
注释会导致针对端点请求的错误


我可以使用PowerMock,但如果可能的话,我想避免使用它。

我最终使用了
MockMvc
,尽管该应用程序不是基于Spring MVC的。此外,我将
SecurityContext
调用分离到另一个服务中,但在此之前,我可以断言
@WithMockUser
注释工作正常

这项工作的关键是在类级别使用以下代码段:

@WebMvcTest(MeController.class)
@Import({ControllerConfiguration.class, BeanConfiguration.class})
public class MeControllerTest {
    // ...
}

使用
@WebMvcTest
有助于不必首先初始化
SecurityContext
。您甚至不必调用
springSecurity()
。您只需像往常一样执行
mockMvc.perform()
操作,对
SecurityContext
的任何调用都将返回您指定的模拟用户,使用
@WithMockUser
或模拟处理此类调用的服务。

编写Junit用于身份验证SecurityContextHolder的更简单方法是模拟它们。以下是它的工作实现。 您可以根据需要添加模拟类,然后设置SecurityContextHolder的上下文,然后使用when()进一步模拟并返回适当的模拟值

    AccessToken mockAccessToken = mock(AccessToken.class);
    Authentication authentication = mock(Authentication.class);
    SecurityContext securityContext = mock(SecurityContext.class);

    when(securityContext.getAuthentication()).thenReturn(authentication);

    SecurityContextHolder.setContext(securityContext);

    when(SecurityContextHolder.getContext().getAuthentication().getDetails()).thenReturn(mockSimpleUserObject);

这个示例代码适用于我。此代码正在使用JUnit 5

@SpringBootTest(class=Application.class)
@AutoConfigureMockMvc//在Spring引导测试中需要这个
公共类LoginControllerIntegrationTest{
//mockMvc不是@Autowired,因为我在@beforeach@之前自定义它
私有MockMvc-MockMvc;
@自动连线
私有WebApplicationContext上下文;
@嘲弄
客户负责人;
@之前
每个()之前的公共无效{
Authentication=mock(OAuth2AuthenticationToken.class);
//用于授权对象的Mockito.whens()
SecurityContext SecurityContext=mock(SecurityContext.class);
当(securityContext.getAuthentication())。然后返回(身份验证);
when(authentication.getPrincipal())。然后返回(principal);
setContext(securityContext);
//使用自定义securityContext设置mockMvc
this.mockMvc=MockMvcBuilders.webAppContextSetup(this.context.build();
}
@试验
public void在登录时为\u提供任何\u OAuth2AuthenticationToken\u,然后将\u重定向到\u logout()引发异常{
最终字符串loginName=“admin”;
//给定
//根据需要操纵委托人
when(principal.getAttribute(“unique_name”)).thenReturn(loginName);
//@formatter:off
//什么时候
this.mockMvc.perform(get(“/login”))
.andDo(print())
//然后
.andExpect(状态().isFound())
.andExpect(重定向到URL(“/注销”);
//@formatter:off
}
}

您实际上不必模拟SecurityContext和身份验证。尝试创建真实对象并设置为SecurityContextHolder。好吧。。。尝试在
@Before
方法上设置
SecurityContextHolder.createEmptyContext()
,但无效。还尝试了:
@Before@Override public void resetMocks(){SecurityContextImpl securityContext=new SecurityContextImpl();securityContext.setAuthentication(新用户名PasswordAuthenticationToken(“user”,null));SecurityContextHolder.setContext(securityContext);reset(employeeRepository);}
仍将主体设置为null…很抱歉,我不清楚这一点。当我需要模拟两个不同的用户时,我应该如何传递模拟的访问令牌?
org.springframework.beans.factory.BeanCreationException: Could not inject field: private org.springframework.security.core.Authentication com.gft.employee.controller.MeControllerTest.authentication; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'org.springframework.security.core.Authentication#0' is expected to be of type 'org.springframework.security.core.Authentication' but was actually of type '$java.security.Principal$$EnhancerByMockitoWithCGLIB$$657040e6'
@WebMvcTest(MeController.class)
@Import({ControllerConfiguration.class, BeanConfiguration.class})
public class MeControllerTest {
    // ...
}
    AccessToken mockAccessToken = mock(AccessToken.class);
    Authentication authentication = mock(Authentication.class);
    SecurityContext securityContext = mock(SecurityContext.class);

    when(securityContext.getAuthentication()).thenReturn(authentication);

    SecurityContextHolder.setContext(securityContext);

    when(SecurityContextHolder.getContext().getAuthentication().getDetails()).thenReturn(mockSimpleUserObject);