Reputation: 796
I am trying to working with project to create junit test for the spring rest webservice. This work fine with the get method but it did works with the post json as input. Here is the code with get method. if anyone help with rest post json junit testing it will appreciated.
@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));
}
}
But I am getting the error as follows
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)
Here is my controller class
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;
}
}
Here is my dispatcher 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>
Upvotes: 6
Views: 9840
Reputation: 457
So the component scanner is picking up your Controller.
See if this works for you:
My approach uses Jackson to JSon encode an object and POST's the Rest service with Json directly. The controller has a utility designed to retrieve the body containing the Json from the HttpServlettRequest. There are other ways to do that I know.
My Test
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());
}
}
}
My Rest Controller So I am receiving Json in the HttpServlettRequest so you will see a utility method to retrieve the body from the request. You may or may not get any use out of it but its here for the purposes of my example.
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;
}
}
Hope that helps good luck.
Upvotes: 0
Reputation: 280132
Assuming
@ContextConfiguration(locations=("/spring/application-config.xml"))
refers to the XML configuration you've shown, there are no @Controller
beans registered and therefore nothing to handle any requests.
Your @ContextConfiguration
should probably be loading the dispatcher-servlet.xml
file which is used by the DispatcherServlet
. That context configuration file should contain
<mvc:annotation-driven />
to register any found @Controller
beans as handlers.
Upvotes: 1