使用HtmlUnit进行Spring MVC测试 - 如何测试JSON响应

时间:2017-06-20 16:09:05

标签: java json spring htmlunit spring-test-mvc

背景:在webapp中搜索表单,带有自动完成/建议。使用jQuery的自动完成功能,在输入几个字符后会显示建议。这些建议作为来自其中一个webapp控制器的JSON数据检索。

问题:我正在通过the HtmlUnit Integration of Spring Test测试应用程序,它适用于Text / Html Pages,但对于JSON响应,设置似乎失败(请参阅下面的错误)。

通过浏览器手动测试(实际的webapp)并从“真实”页面获取JSON也是可行的(参见“json()”测试) - >是否应该通过HtmlUnit / Spring Test设置测试JSON响应,如果是,我做错了什么?

更新(2017-06-21): 使用

@ResponseBody String

并且“手动”构建JSON(不让Spring自动执行)工作;不是我想要的,但至少我可以用这种方式正确测试......

测试:

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

}

控制器:

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):

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 {
}

错误:

    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:
    ...

0 个答案:

没有答案