Tuesday, June 25, 2013

Mock with Jsonpath and Spring MVC

When REST controller returns JSON here is the method to test it

JSON String

[{"id":1,"name":"Sam"},{"id":2,"name":"David"}]

Test

    MockMvc mockMvc;

@Autowired
protected WebApplicationContext wac;

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


@Test
public void shouldGiveSingleDataSetForAvailabilityTypeService() {
try {
 mockMvc.perform(get("/person/1").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(jsonPath("name", is("Sam")));
 mockMvc.perform(get("/person/2").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(jsonPath("name", is("David")));

} catch (Exception e) {
log.error(e.getMessage(), e);
fail();
}

Sunday, June 16, 2013

Testing with Spring 3.2

Spring MVC gives a test framework which MockMvc provides simulation of a servlet container. Its like your running on a mock server. This will help to test all your REST controllers from junit

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:dispatch-servlet.xml" })
public class XXXXXXXXXControllerTest {
@Autowired
XXXXXXController xxxxxxxxxController;       
...

MockMvc mockMvc = MockMvcBuilders.standaloneSetup(xxxxxxxxxController).build();
...
 @Test
 public void shouldXXXXXXXXXXXXXXXXXXXXXX() {
     mockMvc.perform(get("/a/1").accept(MediaType.APPLICATION_JSON)).
                                         andExpect(status().isOk())
   .andExpect(content().string("yyyyyyyyyyyyyyyyyyy"));

}
}
Above is only if we know the name of the controller class. This is good for unit testing the controller classes

OR if you not need to use a given spring config you can use  WebApplicationContext as below

@WebAppConfiguration
public class YYYYYYYYYY{
    MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
protected void shouldXXXXXXXXX() {
getMockMvc().perform(get(restCall)).andExpect(status().isOk());

}

}

Wednesday, June 12, 2013

JSONP response from Spring MVC

How to get a JSONP response from Spring MVC

The best and easy way to do this is attach a filter to HTTP response.

Here is a working example for this


  • Create a filter class and its supported utility classes


public class JsonpBoundryFilter implements Filter {   
public void init(FilterConfig fConfig) throws ServletException {} 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response; 
@SuppressWarnings("unchecked")
Map<String, String[]> parms = httpRequest.getParameterMap(); 
if(parms.containsKey("callback")) {
OutputStream out = httpResponse.getOutputStream(); 
GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse); 
chain.doFilter(request, wrapper);            
byte[] bytes1 = new String(parms.get("callback")[0] + "(").getBytes();
byte[] bytes2 = wrapper.getData();
byte[] bytes3 = new String(");").getBytes();            
ByteBuffer byteBuffer = ByteBuffer.allocate(bytes1.length + bytes2.length + bytes3.length);
byteBuffer.put(bytes1);
byteBuffer.put(bytes2);
byteBuffer.put(bytes3);            
byte[] jsonpResponse = byteBuffer.array();
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
out.write(jsonpResponse); 
out.close();
} else {
chain.doFilter(request, response);
}

public void destroy() {}
}

public class GenericResponseWrapper extends HttpServletResponseWrapper { 
private ByteArrayOutputStream output;    
private FilterServletOutputStream filterStream;
private PrintWriter printWriter;    
private int contentLength;
private String contentType;
 
public GenericResponseWrapper(HttpServletResponse response) {
super(response); 
output = new ByteArrayOutputStream();
filterStream = new FilterServletOutputStream(output);
printWriter = new PrintWriter(output, true);
}  
public byte[] getData() {
return output.toByteArray();
}  
public ServletOutputStream getOutputStream() {
return filterStream;
}  
public PrintWriter getWriter() {
return printWriter;
}  
public void setContentLength(int length) {
this.contentLength = length;
super.setContentLength(length);
}  
public int getContentLength() {
return contentLength;
}  
public void setContentType(String type) {
this.contentType = type;
super.setContentType(type);
}  
public String getContentType() {
return contentType;
}
}

public class FilterServletOutputStream extends ServletOutputStream {
private DataOutputStream stream;
public FilterServletOutputStream(OutputStream output) {
stream = new DataOutputStream(output);
}
public void write(int b) throws IOException {
stream.write(b);
}
public void write(byte[] b) throws IOException {
stream.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
}


  • Add the following configurations to your web.xml

<filter>
<filter-name>jsonpCallbackFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>jsonpBroudryFilter</filter-name> // this name should be in your spring config
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/dispatch-servlet.xml</param-value>
</context-param>
 <listener> 
<listener-class>
                  org.springframework.web.context.ContextLoaderListener
   </listener-class>
</listener>


  • Add following to your spring config as


<bean id="jsonpCallbackFilter" class="com.....JsonpBoundryFilter" />

Sound easy.............  :)