内容类型未从Server Spring设置JSON对象

时间:2014-11-19 20:57:29

标签: java json unit-testing rest spring-mvc

我在Spring中设置了一个REST应用程序,我希望应用程序从我的Java类中返回JSON对象。我尝试让我的单元测试将响应识别为JSON对象,但它仍然失败。

这是应用程序上下文

    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <context:component-scan base-package="com.livingsoup.beaconapp"/>

    <!--<bean id="jacksonObjectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperBuilder" />-->

    <!-- mvc names pace is to set annotation driven set up check name space and classes-->
    <mvc:annotation-driven/>


    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="defaultContentType" value="application/json"/>
    </bean>



    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/database"/>
        <property name="username" value="user"/>
        <property name="password" value="password"/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="annotatedClasses">
            <list>
                <value>com.livingsoup.beaconapp.data.entities.CustomerEntity</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="show_sql">true</prop>
            </props>
        </property>
    </bean>


    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
       <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="customerDOA" class="com.livingsoup.beaconapp.data.services.CustomerDOAImpl"/>

</beans>

这是web.xml文件

<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Beacon MVC Rest App</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

这是我的控制器

@RestController
@RequestMapping(value = "/student")
public class DataController
{
    private CustomerDOA customerDOA;

    @Autowired
    public DataController(CustomerDOA customerDOA)
    {
        this.customerDOA = customerDOA;
    }

    @RequestMapping(value = "/get", method = RequestMethod.GET)
    public @ResponseBody
    Student getData()
    {
        Student student = new Student();
        student.setName("Hello World");
        return student;
    }

    @RequestMapping(value = "/findByPhoneNumber", method = RequestMethod.GET, produces="application/json")
    public @ResponseBody CustomerEntity findByPhoneNumber()
    {
        return customerDOA.findByPhoneNumber("07966487189");
    }

这是我的实体

@Entity
@Table(name = "Customer", schema = "", catalog = "iBeaconServiceDB")
public class CustomerEntity
{
    private int id;
    private String firstName;
    private String lastName;
    private String phoneNumber;
    private String address1;
    private String address2;
    private String address3;
    private String city;
    private String postCode;

    @Id
    @Column(name = "id", nullable = false, insertable = true, updatable = true)
    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    @Basic
    @Column(name = "first_name", nullable = true, insertable = true, updatable = true, length = 255)
    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    @Basic
    @Column(name = "last_name", nullable = true, insertable = true, updatable = true, length = 255)
    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

    @Basic
    @Column(name = "phone_number", nullable = true, insertable = true, updatable = true, length = 25)
    public String getPhoneNumber()
    {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber)
    {
        this.phoneNumber = phoneNumber;
    }

    @Basic
    @Column(name = "address_1", nullable = true, insertable = true, updatable = true, length = 255)
    public String getAddress1()
    {
        return address1;
    }

    public void setAddress1(String address1)
    {
        this.address1 = address1;
    }

    @Basic
    @Column(name = "address_2", nullable = true, insertable = true, updatable = true, length = 255)
    public String getAddress2()
    {
        return address2;
    }

    public void setAddress2(String address2)
    {
        this.address2 = address2;
    }

    @Basic
    @Column(name = "address_3", nullable = true, insertable = true, updatable = true, length = 255)
    public String getAddress3()
    {
        return address3;
    }

    public void setAddress3(String address3)
    {
        this.address3 = address3;
    }

    @Basic
    @Column(name = "city", nullable = true, insertable = true, updatable = true, length = 255)
    public String getCity()
    {
        return city;
    }

    public void setCity(String city)
    {
        this.city = city;
    }

    @Basic
    @Column(name = "post_code", nullable = true, insertable = true, updatable = true, length = 255)
    public String getPostCode()
    {
        return postCode;
    }

    public void setPostCode(String postCode)
    {
        this.postCode = postCode;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CustomerEntity that = (CustomerEntity) o;

        if (id != that.id) return false;
        if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) return false;
        if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) return false;
        if (address3 != null ? !address3.equals(that.address3) : that.address3 != null) return false;
        if (city != null ? !city.equals(that.city) : that.city != null) return false;
        if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false;
        if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false;
        if (phoneNumber != null ? !phoneNumber.equals(that.phoneNumber) : that.phoneNumber != null) return false;
        if (postCode != null ? !postCode.equals(that.postCode) : that.postCode != null) return false;

        return true;
    }

    @Override
    public int hashCode()
    {
        int result = id;
        result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        result = 31 * result + (phoneNumber != null ? phoneNumber.hashCode() : 0);
        result = 31 * result + (address1 != null ? address1.hashCode() : 0);
        result = 31 * result + (address2 != null ? address2.hashCode() : 0);
        result = 31 * result + (address3 != null ? address3.hashCode() : 0);
        result = 31 * result + (city != null ? city.hashCode() : 0);
        result = 31 * result + (postCode != null ? postCode.hashCode() : 0);
        return result;
    }
}

这是我的单元测试

 public void testGetData() throws Exception
    {
        CustomerDOA customerDOA = mock(CustomerDOAImpl.class);
        DataController controller = new DataController(customerDOA);

        MockMvc mockMvc = standaloneSetup(controller).build();
        mockMvc.perform(get("/student/findByPhoneNumber"))
        .andExpect(status().isOk())
        .andExpect(content().contentType("application/json"));
    }

这是我从单元测试中得到的错误

java.lang.AssertionError: Content type not set
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:39)
    at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:72)
    at org.springframework.test.web.servlet.result.ContentResultMatchers$1.match(ContentResultMatchers.java:80)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:153)
    at com.livingsoup.beaconapp.controllers.DataControllerTest.testGetData(DataControllerTest.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

这是从我的单元测试打印出来的响应,我无法理解我做错了什么。为什么我的单元测试不能识别我的JSON输出?

MockHttpServletRequest:
         HTTP Method = GET
         Request URI = /student/findByPhoneNumber
          Parameters = {}
             Headers = {}

             Handler:
                Type = com.livingsoup.beaconapp.controllers.DataController
              Method = public com.livingsoup.beaconapp.data.entities.CustomerEntity com.livingsoup.beaconapp.controllers.DataController.findByPhoneNumber()

               Async:
   Was async started = false
        Async result = null

  Resolved Exception:
                Type = null

        ModelAndView:
           View name = null
                View = null
               Model = null

            FlashMap:

MockHttpServletResponse:
              Status = 200
       Error message = null
             Headers = {}
        Content type = null
                Body = 
       Forwarded URL = null
      Redirected URL = null
             Cookies = []

2 个答案:

答案 0 :(得分:1)

我正在设置我的测试类错误,我没有在我的测试类顶部添加Annotations,而且我本应该将@AutoWired Annotation添加到控制器中并且我还添加了doSetup方法(参见示例)下文)

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml")
@TransactionConfiguration(defaultRollback = true, transactionManager = "txManager")
public class DataControllerTest extends TestCase
{

    @Autowired
    CustomerController dataController;

    MockMvc mockMvc;

    @Before
    public void doSetup()
    {
        mockMvc = standaloneSetup(dataController).build();
    }

    @Test
    public void testGetDataParam() throws Exception
    {
        String phoneNumber = "5551234";

        mockMvc.perform(get("/customer/findByPhoneNumber/" + phoneNumber))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)).andDo(print())
                .andExpect(jsonPath("$.firstName").value("Russell"))
                .andExpect(jsonPath("$.lastName").value("Milburn"));
    }
}

答案 1 :(得分:0)

从我看到你的配置看起来没问题。

但是你缺少Accept标头,我不确定spring-mvc是否需要这个标头集来设置内容类型。但你绝对可以配置spring来忽略accept标头。

contentNegotiationManagerFactoryBean.setIgnoreAcceptHeader()

值得一试或只是设置标题。

mockMvc.perform(get('/..').accept(MediaType.APPLICATION_JSON));