简体   繁体   中英

Unit testing REST Controller with spring-test-mvc

I have upgraded my Spring dependency to Spring 3.1.1.RELEASE and I'm trying to use spring-test-mvc to unit test a simple Controller. I have been following the technique used in Spring REST Controller Test with spring-test-mvc framework , since it seems to have worked for that person, but I have been unsuccessful so far. I think there's some key configuration I"m missing in my test context file.

I get no errors. The reason I know it's not working is because Hello World never gets printed (see Controller). What am I missing here?

Controller:

@Controller
@RequestMapping("/debug")
public class DebugOutputController {

    @RequestMapping(method = RequestMethod.POST)
    public void saveDebugOutput(@RequestBody DebugOutput debugOutput, HttpServletResponse response) {
        System.out.println("Hello World");
    }
}

Test Class:

@RunWith(SpringJUnit4ClassRunner.class) //this lets tests access Spring beans defined in the context config file
@ContextConfiguration(locations={"file:src/test/resources/itest/restAPITestContext.xml"}) //tells the test where to get configuration and beans to be used by the test.
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,  TransactionalTestExecutionListener.class}) //overrides the default stack of listeners
public class ITRestAPI{

@Autowired
private DebugOutputController debugOutputController;

private MockMvc mockMvc;

@Before
public void setUp() throws Exception {
    mockMvc = MockMvcBuilders.standaloneSetup(debugOutputController).build();
}

@After
public void tearDown() throws Exception {
}

@Test
public void shouldPerformPost() throws Exception {
    this.mockMvc.perform(post("/debug"));
}
}

restAPITestContext.xml:

<?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:mvc="http://www.springframework.org/schema/mvc"
   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.1.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <mvc:annotation-driven />
    <mvc:default-servlet-handler />
    <context:component-scan resource-pattern="*DebugOutputController*" base-package="com.company.project.servlet" />    

</beans>

Turns out an HttpMessageNotReadable exception was occurring and I just couldn't see it because I was not logging or printing it anywhere. I found it by building the HTTP request in my test class using the DefaultRequestBuilder class and adding a andDo(print()) :

DefaultRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/debug").contentType(MediaType.APPLICATION_JSON).body(new String("{\"T1\":109.1, \"T2\":99.3}").getBytes());
this.mockMvc.perform(requestBuilder).andDo(print());

So after that, using the output of andDo(print()) , I could see that the HttpMessageNotReadable exception was being thrown, but didn't know the details of the exception or what was causing it. To see the details, I had to add this to the controller class to write the exception details to the response body:

@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public String handleException1(HttpMessageNotReadableException ex)
{
    return ex.getMessage();
}

This revealed the following exception:

Could not read JSON: Unrecognized field "T1" (Class com.company.project.model.device.DebugOutput), not marked as ignorable

which I fixed by adding the @JsonProperty annotation to the setters in my model class:

@JsonProperty("T1")
public void setT1(Float t1) {
    T1 = t1;
}

I just spent ages trying to debug similar issue, and my solution was to do the following:

MvcResult mvcResult = mockMvc
        .perform(
                post("/api/v1/admin/licences/{licenceId}/dataAccess", licenceId)
                        .header(POLLEN_INTERNAL, configuration.getPollenInternalSecret())
                        .header(USER_TYPE, USER_TYPE_OWNER)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(mapper.writeValueAsString(productHierarchyBeans)))
        .andReturn();

This mvcResult variable would contain all the errors or response entities. Then you can analyse it in the debugger or using something like mvcResult.getResponse() or mvcResult.getResolvedException() to find out what works or doesn't, and then fix the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM