Background: Search form in a webapp, with an auto-complete/suggestion. Using jQuery's autocomplete, suggestions are shown after typing a few characters. These suggesitons are retrieved as JSON data from one of the webapp's controllers.
Issue: I am testing the application via the HtmlUnit Integration of Spring Test, which works fine for Text/Html Pages, but for the JSON responses here, the setup seems to fail (see error below).
Manually testing (the actual webapp) via Browser works and fetching JSON from "real" pages works as well ( see "json()" test) -> Should testing JSON responses work via HtmlUnit / Spring Test setup and if yes, what am I doing wrong?
Update (2017-06-21): Using
@ResponseBody String
and building the JSON "manually" (not letting Spring automagically doing it) works; not really what I wanted, but at least I can properly test it this way ...
Test:
package my.project;
import com.gargoylesoftware.htmlunit.*;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.*;
import org.springframework.test.*;
import org.springframework.web.context.support.GenericWebApplicationContext;
import javax.servlet.ServletException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestWebAppConfig.class,
// avoid context caching
MyControllerIT.class})
@WebAppConfiguration
public class MyControllerIT {
protected static final String SERVER_URL = "http://localhost";
protected WebClient webClient;
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;
@Autowired
protected GenericWebApplicationContext webApplicationContext;
@Before
public void setUp() throws Exception {
this.request = new MockHttpServletRequest();
this.request.setServerName("Gondor.Osgiliath");
this.response = new MockHttpServletResponse();
this.webClient = this.initClient();
}
protected final WebClient initClient() throws ServletException {
DefaultMockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(this.webApplicationContext);
MockMvc mockMvc = mockMvcBuilder.build();
WebClient webClient = new WebClient();
webClient.setWebConnection(new MockMvcWebConnection(mockMvc));
return webClient;
}
// https://stackoverflow.com/questions/2932857/html-handling-a-json-response
@Test
public void json() throws Exception {
webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER, "some.proxy", 7890);
Page page = webClient.getPage("https://stackoverflow.com/users/flair/97901.json");
WebResponse webResponse = page.getWebResponse();
String contentType = webResponse.getContentType();
String contentAsString = webResponse.getContentAsString();
}
@Test
public void suggestShouldReturnJSON() throws Exception {
Page page = webClient.getPage(SERVER_URL + MyController.SUGGEST_URL + "?term=asdf");
WebResponse webResponse = page.getWebResponse();
String contentType = webResponse.getContentType();
String contentAsString = webResponse.getContentAsString();
}
@Test
public void suggestShouldReturnJSONViaMockMvc() throws Exception {
MockMvc springMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
ResultActions resultActions = springMvc.perform(MockMvcRequestBuilders
.get(MyController.SUGGEST_URL + "?term=asdf")
.accept(MediaType.APPLICATION_JSON_VALUE));
resultActions.andDo(MockMvcResultHandlers.print());
}
}
Controller:
package my.project;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Arrays;
import java.util.List;
@Controller
public class MyController {
public static final String SUGGEST_URL = "/suggest";
//http://api.jqueryui.com/autocomplete/#option-source
@RequestMapping(value = {SUGGEST_URL,}, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
List<Suggestion> suggest(@RequestParam(name = "term") String term) {
return Arrays.asList(new Suggestion("label1", "value1"), new Suggestion("label2", "value2"));
}
}
Config (Thymeleaf omitted for the moment):
package my.project;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@EnableWebMvc
@ComponentScan(basePackages = {"my.project.*",})
@Configuration
@Import(ThymeleafConfig.class)
abstract class TestWebAppConfig extends WebMvcConfigurerAdapter {
}
Error:
com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: 406 Not Acceptable for http://localhost/suggest?term=asdf
at com.gargoylesoftware.htmlunit.WebClient.throwFailingHttpStatusCodeExceptionIfNecessary(WebClient.java:571)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:396)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:304)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:451)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:436)
at my.project.MyControllerIt.suggestShouldReturnJSON(MyControllerIt.java:
...