与json的春天休息junit岗位

时间:2014-04-04 16:42:07

标签: java json spring rest junit

我正在尝试使用项目为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>

2 个答案:

答案 0 :(得分:1)

假设

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

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

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

<mvc:annotation-driven /> 

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

答案 1 :(得分:0)

因此组件扫描程序正在拿起您的控制器。

看看这是否适合您:

我的方法是使用Jackson直接对Jon编码对象和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;
    }

}

希望有助于好运。