【问题标题】:Spring rest junit post with json带有json的Spring rest junit post
【发布时间】:2014-04-04 16:42:07
【问题描述】:

我正在尝试使用项目为 spring rest webservice 创建 junit 测试。这适用于 get 方法,但它确实适用于 post json 作为输入。这是带有get方法的代码。如果有人帮助休息后 json junit 测试,将不胜感激。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations=("/spring/application-config.xml"))
public class LoginServiceFacadeTestImpl extends AbstractTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }


    @Test
    public void testSearchProductByNameFound() throws Exception {
        String keyword = "";
        this.mockMvc.perform(get("/perlogin")
            .param("q", keyword)
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.name").value(keyword));
    }
}

但我收到如下错误

Time elapsed: 5.477 sec  <<< FAILURE!
java.lang.AssertionError: Status expected:<200> but was:<404>
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
    at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
    at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:549)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141)
    at com.db.mybank.backend.services.presentation.impl.test.LoginServiceFacadeTestImpl.testSearchProductByNameFound(LoginServiceFacadeTestImpl.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
    at $Proxy0.invoke(Unknown Source)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)

这是我的控制器类

package com.backend.controller;

@Controller
@RequestMapping("/")
public class JSONController {

    @Autowired
    private SessionManager sessionManager;

    public JSONController() {
    }   

    @RequestMapping(value = "/perlogin", method = RequestMethod.POST)
    public @ResponseBody
    ValDataVo preLogin(HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse) {
        addDefaultResponseHeaders(httpServletResponse);     
        sessionManager.setHttpSession(httpServletRequest.getSession());
        logger.info("***login session*****::"+httpServletRequest.getSession().getId());

        return resultData;
    }
}

这是我的调度程序 servlet

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:context="http://www.springframework.org/schema/context"  xmlns:p="http://www.springframework.org/schema/p" 
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
       default-autowire="byName">

    <mvc:annotation-driven/>     
    <context:component-scan base-package="com.backend.controller" />

</beans>

【问题讨论】:

  • 您收到 404。我们可以查看您的 mvc 配置吗?
  • @SotiriosDelimanolis 我更新了我的问题
  • 从堆栈跟踪来看,似乎是在另一个测试方法中引发了异常,请您检查一下您的问题吗?
  • 哦,我只是在编辑问题时更改了测试的名称
  • 我恢复了函数名...

标签: java json spring rest junit


【解决方案1】:

假设

@ContextConfiguration(locations=("/spring/application-config.xml"))

指的是您显示的 XML 配置,没有注册 @Controller bean,因此无法处理任何请求。

您的@ContextConfiguration 可能正在加载DispatcherServlet 使用的dispatcher-servlet.xml 文件。该上下文配置文件应包含

<mvc:annotation-driven /> 

将任何找到的@Controller bean 注册为处理程序。

【讨论】:

  • 对不起,我没有更新 @controller 类和调度程序 servlet,我编辑了我的问题
  • @ramesh027 /spring/application-config.xml 是您的调度程序 servlet 配置吗?如果不是,请切换它。
【解决方案2】:

所以组件扫描器正在拾取您的控制器。

看看这是否适合你:

我的方法使用 Jackson 对对象进行 JSON 编码,然后直接使用 Json POST 的 Rest 服务。控制器有一个实用程序,旨在从 HttpServlettRequest 中检索包含 Json 的主体。我知道还有其他方法可以做到这一点。

我的测试

package com.myproject.test;

import static org.junit.Assert.fail;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.myproject.domain.Element;
import com.myproject.model.DbBrokerModel;
import com.myproject.rest.PostJsonRestTest;

// Not sure if you need any of this for your test so just delete it if you don't 
@Configuration
@PropertySource(value={
        "classpath:usermgmt.properties",
        "classpath:ldap.properties",
        "classpath:jdbc.properties",
        "classpath:email.properties"
})
@ContextConfiguration(locations = {
        "file:src/main/webapp/WEB-INF/spring-config.xml",
        "file:src/main/webapp/WEB-INF/conf/applicationContext-email.xml",
        "file:src/main/webapp/WEB-INF/conf/applicationContext-jdbc.xml"

})
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class PostJsonRestTest {


    private static final Logger log = Logger.getLogger(PostJsonRestTest.class);


    @Autowired
    private WebApplicationContext ctx;
    MockMvc mockMvc;

    @InjectMocks
    private PostJsonRest jsonRest;


    // TODO @Inject or @Autowired anything you may need 


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.ctx).build();
    }

    @After
    public void tearDown() throws Exception {
    }


    /**
     * <b>triggerJsonPostTest</b><br/>
     * Explain what you are doing
     * 
     */
    @Test
    public void triggerJsonPostTest() {


        //Set up the model to be converted to Json
        TestModel requestModel = new TestModel();


        // Build the Model object and stuff them with test data
        List<Element> elements = new ArrayList<Element>();
        requestModel.setElementId("123");
        requestModel.setElementType("change");
        requestModel.setElementsAffected(3);
        requestModel.setChanges(elements);



        try {
            //Convert the Test Model To JSon
            ObjectMapper objectMapper = new ObjectMapper();
            byte[] requestJson =  objectMapper.writeValueAsBytes(requestModel);

            //Call your rest contoller 
            MvcResult result = this.mockMvc.perform(post("/test/receive-json")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(requestJson))
                    .andDo(print())
                    .andExpect(status().isOk())             
                    .andReturn();
            //TODO Wrtie a bunch of validation for the return OBJECT
            //TODO: Remember to test for positive and negative results in seperate @Test's 


        } catch (Exception e) {
            e.printStackTrace();
            fail(e.getMessage());
        }
    }

}

我的休息控制器 因此,我在 HttpServlettRequest 中接收 Json,因此您将看到一个实用方法来从请求中检索正文。您可能会或可能不会从中得到任何用处,但出于我的示例的目的,它在这里。

package com.myproject.rest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * <b>PostJsonRest</b><br/>
 * Rest Controller Example
 * @author dhargis
 *
 *
 */
@Controller
public class PostJsonRest {

    private static final Logger log = Logger.getLogger(PostJsonRest.class);


    //TODO You may want to @Inject or @Autowire something here 

    /**
     * <b>receivePostJSon</b><br/>
     * Listens for properly formated JSon formated request of object type TestModel
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(
            value = "/trigger/receive-json", 
            method = RequestMethod.POST, 
            produces = {MediaType.APPLICATION_JSON_VALUE})
    @ResponseBody
    public void receivePostJSon(HttpServletRequest request, HttpServletResponse response) throws Exception{

        String body = "";
        try{
            //See below utility class 
            body =  getBody(request);

            //TODO You may want to log something here 

        }
        catch(IOException e){

            log.warn("Error: Problems parsing incoming JSON request  ", e);

        }

        finally{


        }

        // TODO REMOVE Temporary Output to the command line before deployment
        System.out.println(body);

    }

    /**
     * <b>getBody</b><br/>
     * This little utility class will give you the body containing the JSON
     * @param request
     * @return
     * @throws IOException
     */

    private String getBody(HttpServletRequest request) throws IOException {
        String body = null;
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            log.error("Error while reading the request body", ex);
            throw ex;
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    log.error("Error while closing the reading for request body", ex);
                    throw ex;
                }
            }
        }
        body = stringBuilder.toString();
        return body;
    }

}

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-23
    • 2017-01-04
    • 2021-06-27
    • 2012-10-19
    • 2011-05-22
    • 2020-01-18
    • 2018-02-11
    • 1970-01-01
    相关资源
    最近更新 更多