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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With