Spring 测试 - java.lang.IllegalArgumentException:没有足够的变量值可用于扩展
Spring Testing - java.lang.IllegalArgumentException: Not enough variable values available to expand
我正在为下面的 REST 控制器编写单元测试,它采用 UserID 并向该用户授予权限列表。
@RestController
@RequestMapping("/user")
@Api(value = "User", description = "User API")
public class UserController{
// some code
@RequestMapping(method = RequestMethod.POST, value = "/{userId}/grantAuthz")
@ApiOperation(value = "GrantAuthz", notes = "Grant Authorization")
public Collection<UserEntity.UserAuthz> grantAuthz(@PathVariable("userId") String userId,
@RequestBody ArrayList<String> authorities) {
UserEntity userEntity = userRepository.findOne(userId);
if(userEntity == null) {
//TODO: throw and send resource not found
return null;
}
log.debug("Authorities to be granted to user " + userId + " are : " + authorities);
for(String authz : authorities) {
log.debug("Adding Authorization " + authz);
userEntity.addUserAuthz(authz);
}
userRepository.save(userEntity);
return userEntity.getAuthorities();
}
}
我为 UserController 编写了以下单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class UserControllerTest {
private final Log log = LogFactory.getLog(getClass());
private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Charset.forName("utf8"));
private MockMvc mockMvc;
private HttpMessageConverter mappingJackson2HttpMessageConverter;
private final String USER_URL = "/{userId}/grantAuthz";
private final String USER_ID = "111";
private final String USER_NAME = "MockUser";
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private UserRepository userRepository;
private String createdToken = null;
@Autowired
void setConverters(HttpMessageConverter<?>[] converters) {
this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream().filter(
hmc -> hmc instanceof MappingJackson2HttpMessageConverter).findAny().get();
Assert.assertNotNull("the JSON message converter must not be null",
this.mappingJackson2HttpMessageConverter);
}
@Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONObject json = new JSONObject();
json.put("grantList",grantList);
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL)
.contentType(contentType)
.param("userId",USER_ID)
.param("authorities",json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
}
执行时,我的测试抛出非法参数异常:
"Not enough variable values available to expand 'userId'"
我在测试中使用 .param() 方法发送所需的 URL 参数,我做错了什么?我提出了这个可能重复的问题,但没有发现它很有用。 Using RestTemplate in Spring. Exception- Not enough variables available to expand
我发现我做错了什么,在这里使用 param() 方法不是正确的方法,因为我的控制器方法中有 @PathVariable
和 @RequestBody
作为参数。
public Collection<UserEntity.UserAuthz> grantAuthz(@PathVariable("userId") String userId,
@RequestBody ArrayList<String> authorities) {
所以我在测试的post()
方法中通过了@PathVariable
MockMvcRequestBuilders.post(USER_URL,USER_ID)
由于所需的类型是 @RequestBody ArrayList<String>
而不是使用 JSONObject
我使用 JSONArray
并使用 content() 方法将 JSONArray 作为字符串发送。
这是我对测试方法所做的更改。
@Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONArray json = new JSONArray();
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL,USER_ID)
.contentType(contentType)
.content(json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
@Test
public void getOneContactAPI() throws Exception {
String id = "8";
mvc.perform(MockMvcRequestBuilders.get("/api/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("id").exists());
}
我正在为下面的 REST 控制器编写单元测试,它采用 UserID 并向该用户授予权限列表。
@RestController
@RequestMapping("/user")
@Api(value = "User", description = "User API")
public class UserController{
// some code
@RequestMapping(method = RequestMethod.POST, value = "/{userId}/grantAuthz")
@ApiOperation(value = "GrantAuthz", notes = "Grant Authorization")
public Collection<UserEntity.UserAuthz> grantAuthz(@PathVariable("userId") String userId,
@RequestBody ArrayList<String> authorities) {
UserEntity userEntity = userRepository.findOne(userId);
if(userEntity == null) {
//TODO: throw and send resource not found
return null;
}
log.debug("Authorities to be granted to user " + userId + " are : " + authorities);
for(String authz : authorities) {
log.debug("Adding Authorization " + authz);
userEntity.addUserAuthz(authz);
}
userRepository.save(userEntity);
return userEntity.getAuthorities();
}
}
我为 UserController 编写了以下单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class UserControllerTest {
private final Log log = LogFactory.getLog(getClass());
private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Charset.forName("utf8"));
private MockMvc mockMvc;
private HttpMessageConverter mappingJackson2HttpMessageConverter;
private final String USER_URL = "/{userId}/grantAuthz";
private final String USER_ID = "111";
private final String USER_NAME = "MockUser";
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private UserRepository userRepository;
private String createdToken = null;
@Autowired
void setConverters(HttpMessageConverter<?>[] converters) {
this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream().filter(
hmc -> hmc instanceof MappingJackson2HttpMessageConverter).findAny().get();
Assert.assertNotNull("the JSON message converter must not be null",
this.mappingJackson2HttpMessageConverter);
}
@Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONObject json = new JSONObject();
json.put("grantList",grantList);
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL)
.contentType(contentType)
.param("userId",USER_ID)
.param("authorities",json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
}
执行时,我的测试抛出非法参数异常:
"Not enough variable values available to expand 'userId'"
我在测试中使用 .param() 方法发送所需的 URL 参数,我做错了什么?我提出了这个可能重复的问题,但没有发现它很有用。 Using RestTemplate in Spring. Exception- Not enough variables available to expand
我发现我做错了什么,在这里使用 param() 方法不是正确的方法,因为我的控制器方法中有 @PathVariable
和 @RequestBody
作为参数。
public Collection<UserEntity.UserAuthz> grantAuthz(@PathVariable("userId") String userId,
@RequestBody ArrayList<String> authorities) {
所以我在测试的post()
方法中通过了@PathVariable
MockMvcRequestBuilders.post(USER_URL,USER_ID)
由于所需的类型是 @RequestBody ArrayList<String>
而不是使用 JSONObject
我使用 JSONArray
并使用 content() 方法将 JSONArray 作为字符串发送。
这是我对测试方法所做的更改。
@Test
public void testGrantAuthorizationForUser() throws Exception{
Optional<UserEntity> userEntityAuthz = userRepository.findOneByUsername(USER_NAME);
Set<String> expectedAuthzList = (LinkedHashSet)userEntityAuthz.get().getAuthorizations();
List<String> grantList = new ArrayList<>();
grantList.add("ABC");
grantList.add("DEF");
grantList.add("GHI");
grantList.add("JKL");
grantList.add("MNO");
grantList.add("PQR");
grantList.add("STU");
grantList.add("VWX");
grantList.add("YZA");
JSONArray json = new JSONArray();
MvcResult grantAuthzResult = mockMvc.perform(MockMvcRequestBuilders.post(USER_URL,USER_ID)
.contentType(contentType)
.content(json.toString()))
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
@Test
public void getOneContactAPI() throws Exception {
String id = "8";
mvc.perform(MockMvcRequestBuilders.get("/api/contact/{id}",id).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("id").exists());
}