Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Spring Testing - java.lang.IllegalArgumentException: Not enough variable values available to expand

Ask Question

I am writing Unit Tests for the below REST Controller which takes a UserID and grants a List of Authorities to that user.

    @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();

I wrote the below Unit Test for the 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();

When executed, my test is throwing an Illegal Argument Exception:

"Not enough variable values available to expand 'userId'"

I am sending the required URL Parameters using the .param() method in the test, what am I doing wrong ? I reffered this possible duplicate question but did not find it much useful. Using RestTemplate in Spring. Exception- Not enough variables available to expand

I found out what I am doing wrong, using param() method is not the right way here as I have @PathVariable and @RequestBody in my Controller Methods as the parameters.

public Collection<UserEntity.UserAuthz> grantAuthz(@PathVariable("userId") String userId,
                                                           @RequestBody ArrayList<String> authorities) {

So I passed the @PathVariable in the post() method of the test.

MockMvcRequestBuilders.post(USER_URL,USER_ID)

As the required type is @RequestBody ArrayList<String> instead of using the JSONObject I used JSONArrayand used the content() method to send the JSONArray as the string.

Here are the changes I have made to the Test Method.

   @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();
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());
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.