在REST控制器中,我有几种方法需要创建合同测试,而且我不知道如何为通过测试提供Principal。
Controller中具有参数Principal的方法之一:
@PreAuthorize("hasRole('USER')")
@GetMapping("/current")
public Details getCurrent(Principal principal) {
return houseManager.getById(Principals.getCurrentUserId(principal));
}
我已经创建了用于测试的基类:
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = {Controller.class})
@ContextConfiguration(classes = {TestConfig.class, ControllerTestConfig.class})
@ComponentScan(basePackageClasses = {Controller.class})
@AutoConfigureStubRunner
public class ControllersWithSecurityBase {
@Autowired
privet Service service;
@Autowired
WebApplicationContext context;
@Mock
private Principal mockedPrincipal;
RestAssuredMockMvc.standaloneSetup(new Controller(service));
RequestBuilder requestBuilder = MockMvcRequestBuilders
.get("/")
.with(user("user")
.password("password")
.roles("USER"))
.principal(mockedPrincipal)
.accept(MediaType.APPLICATION_JSON);
MockMvc mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.defaultRequest(requestBuilder)
.apply(springSecurity())
.build();
RestAssuredMockMvc.mockMvc(mockMvc);
}
合同:
Contract.make {
name("Should find current by principal")
request {
method(GET)
urlPath(".../current")
}
response {
status(200)
}
}
由于mvn全新安装,我有下一个异常:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: org.springframework.security.authentication.UsernamePasswordAuthenticationToken cannot be cast to java.util.Map
正确的模拟主体和通过测试我需要做什么?
答案 0 :(得分:0)
设置基类并放心使用时,您需要使用AuthenticationPrincipalArgumentResolver传递自定义参数解析器
mockMvc(
standaloneSetup( controller )
.setCustomArgumentResolvers( new AuthenticationPrincipalArgumentResolver() )
您还可以传入将在每次测试中添加WithMockUser的插件
<build>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>${maven-replacer-plugin.version}</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>target/generated-test-sources/**/*.java</include>
</includes>
<regex>true</regex>
<regexFlags>
<regexFlag>MULTILINE</regexFlag>
</regexFlags>
<replacements>
<replacement>
<token>@Test</token>
<value>@WithMockUser
@Test</value>
</replacement>
</replacements>
</configuration>
</plugin>
</plugins>
</build>
请记住将WithMockUser作为标准名称传递。
答案 1 :(得分:0)
我的项目使用Oauth2安全性。
因此,为了在合同测试中模拟Principal对象,我创建了OAuth2AuthenticationDetails的bean(此类实现Principal接口)。
具有OAuth2AuthenticationDetails Bean的类配置为:
package com.example.config.fakesecurityconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import java.util.*;
@Configuration
public class OAuth2TestConfig {
@Bean
public OAuth2Authentication oAuth2Authentication() {
return new OAuth2Authentication(getStoredRequest(), getUserAuthentication());
}
@Bean
public OAuth2AuthenticationDetails oAuth2AuthenticationDetails() {
MockHttpServletRequest request = new MockHttpServletRequest();
return new OAuth2AuthenticationDetails(request);
}
private OAuth2Request getStoredRequest() {
Set<String> scope = new HashSet<>();
scope.add("read");
scope.add("write");
return new OAuth2Request(
Collections.EMPTY_MAP,
"clientId",
getGrantedAuthorityCollection(),
true,
scope,
Collections.EMPTY_SET,
null,
Collections.EMPTY_SET,
Collections.EMPTY_MAP);
}
private Authentication getUserAuthentication() {
String credentials = "PROTECTED";
Authentication authentication = new TestingAuthenticationToken(getPrincipalMap(), credentials, getGrantedAuthorityAsList());
return new OAuth2Authentication(getStoredRequest(), authentication);
}
private Map<String, String> getPrincipalMap() {
Map<String, String> principalMap = new LinkedHashMap<>();
principalMap.put("id", "5c49c98d3a0f3a23cd39a720");
principalMap.put("username", "TestUserName");
principalMap.put("password", "TestPassword");
principalMap.put("createdAt", "2018-06-14 10:35:05");
principalMap.put("userType", "USER");
principalMap.put("authorities", getGrantedAuthorityCollectionAsMap().toString());
principalMap.put("accountNonExpired", "true");
principalMap.put("accountNonLocked", "true");
principalMap.put("credentialsNonExpired", "true");
principalMap.put("enabled", "true");
principalMap.put("uniqueId", "null");
principalMap.put("uniqueLink", "fc3552f4-0cdf-494d-bc46-9d1e6305400a");
principalMap.put("uniqueLinkCreatedAt", "2019-09-06 10:44:36");
principalMap.put("someId", "59b5a82c410df8000a83a1ff");
principalMap.put("otherId", "59b5a82c410df8000a83a1ff");
principalMap.put("name", "TestName");
return principalMap;
}
private Collection<GrantedAuthority> getGrantedAuthorityCollection() {
return Arrays.asList(
new SimpleGrantedAuthority("ROLE_ADMIN"),
new SimpleGrantedAuthority("ROLE_USER")
);
}
private List<GrantedAuthority> getGrantedAuthorityAsList() {
return new ArrayList<>(getGrantedAuthorityCollection());
}
private LinkedHashMap<String, GrantedAuthority> getGrantedAuthorityCollectionAsMap() {
LinkedHashMap<String, GrantedAuthority> map = new LinkedHashMap<>();
for (GrantedAuthority authority : getGrantedAuthorityCollection()) {
map.put("authority", authority);
}
return map;
}
}
结果,我的合同测试基类为:
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = {Controller.class})
@ContextConfiguration(classes = {TestConfig.class, OAuth2TestConfig.class})
@ComponentScan(basePackageClasses = {Controller.class})
@AutoConfigureStubRunner
@WebAppConfiguration
public abstract class HousesControllersSecuredBase {
@Autowired
private Service service;
@Autowired
private WebApplicationContext context;
@Autowired
private OAuth2Authentication oAuth2Authentication;
@Autowired
private OAuth2AuthenticationDetails oAuth2AuthenticationDetails;
@Autowired
private MockMvc mockMvc;
@Before
public void settingUpTests() {
RestAssuredMockMvc.standaloneSetup(Controller(houseService));
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
RestAssuredMockMvc.mockMvc(mockMvc);
oAuth2Authentication.setDetails(oAuth2AuthenticationDetails);
RestAssuredMockMvc.authentication =
RestAssuredMockMvc.principal(oAuth2Authentication);
}
@After
public void ShuttingDownTests() {
RestAssuredMockMvc.reset();
}
}