Integration Testing of Spring MVC Applications: Write Clean Assertions with JsonPath

The previous parts of my Spring MVC Test tutorial have described how we can write integration tests for a REST API. Although the techniques described in those blog posts are useful, the problem is that our assertions were not very elegant. Our assertions were basically ensuring that the body of the HTTP response contained the "right" strings.

This approach has two problems:

  • It is not very readable, especially if the returned JSON is large. Since our tests should act as a documentation for our code, this is a huge problem.
  • It is very hard to write tests which ensure that the ordering of collections is correct without sacrificing readability.

Luckily for us, there is a better way to do this. JsonPath is to JSON what XPath is to XML. It provides an easy and readable way to extract parts of a JSON document. This blog post describes how we can write assertions by using the Spring MVC Test and the Java implementation of JsonPath.

These blog posts describe the structure of our example application and teaches us to write integration tests to it without using the JsonPath library (This blog post skips the details described in these blog posts):

Let's get started and find out how we can get the required dependencies with Maven.

Getting Required Dependencies with Maven

We can get the required dependencies with Maven by following these steps:

  1. Declare the Hamcrest dependency (version 1.3) in the pom.xml file.
  2. Declare the JUnit dependency (version 4.11) in the pom.xml file and exclude the hamcrest dependencies.
  3. Declare the Spring Test (version 3.2.2.RELEASE) dependency in the pom.xml file.
  4. Add JsonPath dependencies (version 0.8.1) to the pom.xml file.

The relevant dependency declarations looks as follows:

<dependency>
	<groupId>org.hamcrest</groupId>
	<artifactId>hamcrest-all</artifactId>
	<version>1.3</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.11</version>
	<scope>test</scope>
	<exclusions>
		<exclusion>
			<artifactId>hamcrest-core</artifactId>
			<groupId>org.hamcrest</groupId>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test</artifactId>
	<version>3.2.2.RELEASE</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>com.jayway.jsonpath</groupId>
	<artifactId>json-path</artifactId>
	<version>0.8.1</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>com.jayway.jsonpath</groupId>
	<artifactId>json-path-assert</artifactId>
	<version>0.8.1</version>
	<scope>test</scope>
</dependency>

Let's move and find out how we can write assertions by using JsonPath.

Writing Integration Tests

We can write integration tests by executing the tested operation and making assertions against the returned JSON document. We can create a new assertion by following these steps:

  1. Create a JsonPath expession which fetches the preferred part from the returned JSON document (Get more information about the JsonPath notation).
  2. Make an assertion against the fetched part by using a Hamcrest matcher.
  3. Use the jsonPath() method of MockMvcResultMatchers class to verify that the assertion is true and pass the objects created in phases one and two as method parameters.

Enough with theory. Let’s move on and find out how we can write assertions against JSON documents. The following subsections describe how we can write assertions against JSON documents which contains either the information of a single object or the information of multiple objects.

Single Object

This subsection describes how we can ensure that the JSON document which contains the information of a single object is correct. As an example we will write an integration test for a controller method which is used to delete the information of an existing todo entry. After the todo entry has been deleted successfully, its information is returned back to the client. The returned JSON looks as follows:

{
	"id":1,
	"description":"Lorem ipsum",
	"title":"Foo"
}

We can write the integration test by following these steps:

  1. Use the @ExpectedDatabase annotation to ensure that the todo entry is deleted.
  2. Perform a DELETE request to url '/api/todo/1'. Set the logged in user.
  3. Verify that the returned HTTP status code is 200.
  4. Verify that the content type of the response is 'application/json' and its character set is 'UTF-8'.
  5. Get the id of the deleted todo entry by using the JsonPath expression $.id and verify that the id is 1.
  6. Get the description of the deleted todo entry by using the JsonPath expression $.description and verify that the description is is "Lorem ipsum".
  7. Get the title of the deleted todo entry by using the JsonPath expression $.title and verify that the title is "Foo".

The source code of our integration test looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.ExpectedDatabase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.test.web.server.MockMvc;
import org.springframework.test.web.server.samples.context.WebContextLoader;

import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.server.samples.context.SecurityRequestPostProcessors.userDetailsService;
import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, classes = {ExampleApplicationContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
@DatabaseSetup("toDoData.xml")
public class ITTodoControllerTest {

    //Add web application context here

    private MockMvc mockMvc;

    //Add setUp() method here

    @Test
    @ExpectedDatabase("toDoData-delete-expected.xml")
    public void deleteById() throws Exception {
        mockMvc.perform(delete("/api/todo/{id}", 1L)
                .with(userDetailsService(IntegrationTestUtil.CORRECT_USERNAME))
        )
                .andExpect(status().isOk())
                .andExpect(content().mimeType(IntegrationTestUtil.APPLICATION_JSON_UTF8))
                .andExpect(jsonPath("$.id", is(1)))
                .andExpect(jsonPath("$.description", is("Lorem ipsum")))
                .andExpect(jsonPath("$.title", is("Foo")));
    }
}

Collection of Objects

This subsection describes how we can write assertions which ensure that the JSON document containing a collection of objects is correct. We will take a look at two different situations:

  • The objects are always returned in the same order.
  • The objects are returned in a random order.

Let's continue our journey.

Objects Returned in the Same Order

When the user wants to get all todo entries which are stored in the database, the entries are always returned in the same order. The returned JSON looks as follows:

[
	{
		"id":1,
		"description":"Lorem ipsum",
		"title":"Foo"
	},
	{
		"id":2,
		"description":"Lorem ipsum",
		"title":"Bar"
	}
]

We can write our integration test by following these steps:

  1. Use the @ExpectedDatabase annotation to verify that no changes is made to the database.
  2. Perform a GET request to url '/api/todo'. Set the logged in user.
  3. Verify that the returned HTTP status code is 200.
  4. Verify that the content type of the response is 'application/json' and its character set 'UTF-8'.
  5. Fetch the collection of todo entries by using JsonPath expression $ and ensure that two todo entries are returned.
  6. Use the JsonPath expressions $[0].id, $[0].description and $[0].title to get the id, description and title of the first todo entry. Verify that its information is correct.
  7. Use the JsonPath expressions $[1].id, $[1].description and $[1].title to get the id, description and title of the second todo entry. Verify that its information is correct.

The source code of our integration test looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.ExpectedDatabase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.test.web.server.MockMvc;
import org.springframework.test.web.server.samples.context.WebContextLoader;

import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.server.samples.context.SecurityRequestPostProcessors.userDetailsService;
import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, classes = {ExampleApplicationContext.class})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class })
@DatabaseSetup("toDoData.xml")
public class ITTodoControllerTest {

    //Add web application context here

    private MockMvc mockMvc;

    //Add setUp() method here

    @Test
    @ExpectedDatabase("toDoData.xml")
    public void findAll() throws Exception {
        mockMvc.perform(get("/api/todo")
                .with(userDetailsService(IntegrationTestUtil.CORRECT_USERNAME))
        )
                .andExpect(status().isOk())
                .andExpect(content().mimeType(IntegrationTestUtil.APPLICATION_JSON_UTF8))
				.andExpect(jsonPath("$", hasSize(2)))
				.andExpect(jsonPath("$[0].id", is(1)))
				.andExpect(jsonPath("$[0].description", is("Lorem ipsum")))
				.andExpect(jsonPath("$[0].title", is("Foo")))
				.andExpect(jsonPath("$[1].id", is(2)))
				.andExpect(jsonPath("$[1].description", is("Lorem ipsum")))
				.andExpect(jsonPath("$[1].title", is("Bar")));
    }
}

Objects Returned in a Random Order

When a validation of an added or updated todo entry fails, our example application returns the field errors back to the client of our REST API. The problem is that we cannot guarantee the order in which the fields are validated. This means that the field errors are returned in a random order. One JSON document which contains the returned field errors looks as follows:

{
	"fieldErrors":[
		{
			"path":"description",
			"message":"The maximum length of the description is 500 characters."
		},
		{
			"path":"title",
			"message":"The maximum length of the title is 100 characters."
		}
	]
}

We can write an write an integration test, which verifies that field errors are returned when a new todo entry which contains invalid information is added, by following these steps:

  1. Use the @ExpectedDatabase annotation to verify that no changes are made to the database.
  2. Create the title and description of the todo entry. Ensure that both the title and description are too long.
  3. Create a new TodoDTO object and set its title and description.
  4. Perform a POST request to the url '/api/todo'. Set the content type of the request to 'application/json'. Set the character set of the request to 'UTF-8'. Transform the created object into a correct format and send it in the body of the request. Set the logged in user.
  5. Verify that the content type of the response is 'application/json' and its character set is 'UTF-8'.
  6. Fetch the field errors by using the JsonPath expression $.fieldErrors and ensure that two field errors are returned.
  7. Use the JsonPath expression $.fieldErrors[*].path to fetch all available paths. Ensure that field errors about title and description fields are available.
  8. Use the JsonPath expression $.fieldErrors[*].message to fetch all available error messages. Ensure that error messages concerning title and description fields are returned.

The source code of our integration test looks as follows:

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.ExpectedDatabase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.test.web.server.MockMvc;
import org.springframework.test.web.server.samples.context.WebContextLoader;

import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.server.samples.context.SecurityRequestPostProcessors.userDetailsService;
import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, classes = {ExampleApplicationContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class})
@DatabaseSetup("toDoData.xml")
public class ITTodoControllerTest {

    //Add web application context here

    private MockMvc mockMvc;

    //Add setUp() method here

    @Test
    @ExpectedDatabase("toDoData.xml")
    public void addTodoWhenTitleAndDescriptionAreTooLong() throws Exception {
        String title = TodoTestUtil.createStringWithLength(101);
        String description = TodoTestUtil.createStringWithLength(501);
        TodoDTO added = TodoTestUtil.createDTO(null, description, title);

        mockMvc.perform(post("/api/todo")
                .contentType(IntegrationTestUtil.APPLICATION_JSON_UTF8)
                .body(IntegrationTestUtil.convertObjectToJsonBytes(added))
                .with(userDetailsService(IntegrationTestUtil.CORRECT_USERNAME))
        )
                .andExpect(status().isBadRequest())
                .andExpect(content().mimeType(IntegrationTestUtil.APPLICATION_JSON_UTF8))
                .andExpect(jsonPath("$.fieldErrors", hasSize(2)))
				.andExpect(jsonPath("$.fieldErrors[*].path", containsInAnyOrder("title", "description")))
				.andExpect(jsonPath("$.fieldErrors[*].message", containsInAnyOrder(
						"The maximum length of the description is 500 characters.",
						"The maximum length of the title is 100 characters."
				)));                
    }
}

Summary

We have now written integration tests to a REST API by using Spring MVC Test and JsonPath. This blog post has taught us four things:

  • We learned how we can get the required JsonPath dependencies with Maven.
  • We learned how we can write assertions against the JSON representation of a single object.
  • We learned how we can write assertions against the JSON representation of a collection of objects.
  • We learned that writing assertions with JsonPath improves the readability of our tests.

P.S. You can get the example application of this blog post from Github.

If you want to save time by writing less test code, take a look at my upcoming Test With Spring Course.
11 comments… add one
  • Nirmal Mar 16, 2014 @ 8:37

    Update: I removed some unrelevant code to make this question a bit more clear - Petri

    This is my Controller Method

    
    @RequestMapping(value="/TradesMngJson.do")
    public @ResponseBody List getFilteredEMFTradesAsJson(@ModelAttribute("model") ModelMap model,
    		HttpServletRequest request, 
    		@RequestParam(required=false,value="source") String paramSource,
    		@RequestParam(required=false,value="status") String paramStatus,
    		@RequestParam(required=false,value="account") String paramAccount,
    		@RequestParam(required=false,value="fromDate") String paramFromDate,
    		@RequestParam(required=false,value="toDate") String paramToDate,
    		@RequestParam(required=false,value="rcvdDate") String paramRcvdDate){
    
    	List tradeList;
    	try{
    		//I removed some code because it wasn't relevant
    
    		tradeList=(List)(List) tradeInService.getFilteredTrades(filterMap);
    		tradeList=(List)(List)tradeInService.filterByDates(
    				(List)(List)tradeList,
    				fromDate,
    				toDate
    		);
    		if(paramSource!=null && paramSource.trim()!=""){ 
    			model.addAttribute("source",paramSource);
    		}
    		
    		//Removed some code again because it wasn't relevant
    
    		if(tradeList.size() == 0){
    			List error = new ArrayList();
    			error.add(new ErrorBean(
    					constants.NODATA_ERROR_CODE, 
    					constants.NODATA_ERROR_MSG_TO_DISPLAY
    			));
    			return (List)(List) error;
    		}else{
    			return tradeList;
    		}
    	} catch(Exception e){
    		logger.error("Exception:", e);
    		List error = new ArrayList();
    		error.add(new ErrorBean(
    				"100", 
    				"No data available, contact to admin"
    		));
    		tradeList = (List)(List) error;
    		return tradeList;
    	}
    }
    
    

    This is the test case that i have written for the Controller Method.

    
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration({
    		"file:src/main/webapp/WEB-INF/spring/appServlet/test-config.xml" 
    })
    public class EMFTradesControllerMock {
    
    	@InjectMocks
    	EMFTradesController emftradescontrollermock;
    
    	@Mock
    	TradeInService tradeInServicemock;
    
    	private MockMvc mockEMF;
    
    	MockHttpServletRequest request = new MockHttpServletRequest();
    	ModelMap model = new ModelMap();
    
    	@Autowired
    	private WebApplicationContext webApplicationContext;
    
    	@Before
    	public void setUp() throws Exception {
    		MockitoAnnotations.initMocks(this);
    		mockEMF = MockMvcBuilders.standaloneSetup(emftradescontrollermock).build();
    	}
    
    	@SuppressWarnings("unchecked")
    	@Test
    	public void test() throws Exception {
    		TradeOverviewBean bean = new TradeOverviewBeanBuilder().aCCT_CD("1")
    				.tPH_TRD_SEQ_NO((long) 62).source("BR").transactionType("BUY")
    				.tRD_REF_NO((long) -100001).cUSIP("121899DJ4").status("N")
    				.tOUCH_COUNT(1).brokerCode("BEAR").executionCurrency("USD")
    				.executionPrice((double) 101)
    				.executionAmount((double) 1020347.22).build();
    		
    		when(tradeInServicemock.getFilteredTrades((Map) Mockito.anyMap()))
    				.thenReturn(Arrays.asList(bean));
    		when(tradeInServicemock.filterByDates(
    				(List) Mockito.anyList(),
    				(Date) Mockito.any(), 
    				(Date) Mockito.any())
    		)
    				.thenReturn(Arrays.asList(bean));
    				
    		mockEMF.perform(get("/TradesMngJson.do"))
    				.andExpect(status().isOk())
    				.andExpect(content().contentType(
    						MediaType.parseMediaType("application/json;charset=UTF-8"
    				)))
    				.andExpect(jsonPath("$.source").value("BR"));
        }
    }
    
    

    When i run the test case i get the error

    java.lang.AssertionError: JSON path$.source expected: but was:

    Just wanted to know where i am going wrong. According to me everything seems to be fine. but the data which i am passing is not returning in the JSON path. I followed all the procedures to test a json data.

    Please suggest me an idea

    • Petri Mar 16, 2014 @ 12:56

      It seems that you are expecting that the information which you add to the ModelMap object would be returned back to the client as JSON document. Spring MVC doesn't work this way.

      When you annotate a controller method with the @ResponseBody annotation, Spring MVC transforms the information returned by this method into a JSON document (or an XML document depending from your configuration) and returns it back to the client.

      If you want to return the information which you add to the ModelMap object as well, you have to create a wrapper class which contains all returned information. In other words, your code could look like this:

      
      //The wrapper class
      public class TradeInfo {
      
      	private String source;
      	
      	private List tradeList;
      	
      	public TradeInfo() {
      	}
      	
      	//Getters and setters are omitted
      }
      
      //Example controller method
      @RequestMapping(value="/TradesMngJson.do")
      public @ResponseBody TradeInfo getFilteredEMFTradesAsJson(
      		HttpServletRequest request, 
      		@RequestParam(required=false,value="source") String paramSource,
      		@RequestParam(required=false,value="status") String paramStatus,
      		@RequestParam(required=false,value="account") String paramAccount,
      		@RequestParam(required=false,value="fromDate") String paramFromDate,
      		@RequestParam(required=false,value="toDate") String paramToDate,
      		@RequestParam(required=false,value="rcvdDate") String paramRcvdDate){
      
      		//Get tradelist
      		List tradeList = ...
      		
      		//Create returned object
      		TradeInfo info = new TradeInfo();
      		info.setSource("source")
      		info.setTradeList(tradeList)
      		
      		//Return the information which is transformed into JSON.
      		return info;
      }
      
      
  • Rahini Aug 7, 2015 @ 13:59

    This method is from my controller. Can you please explain that corresponding possible test cases in junit using mockito?
    -----------------------------------

    
    @Transactional
    @RequestMapping(value = "/getRunId", method = RequestMethod.GET)
    @ResponseBody
    public String getRunId(@RequestParam(value = "date1", required = false) String date1, 
    					@RequestParam(value = "date2", required = false) String date2) {
    	List runIdList = analyticsService.getRunId(date1, date2);
    	java.util.Iterator runIdIterator = runIdList.iterator();
    	
    	JSONArray ja = new JSONArray();
    	
    	while (runIdIterator.hasNext()) {
    		JSONObject obj = new JSONObject(); 
    		JobRunStepLog itr = runIdIterator.next();
    		obj.put("runid",itr.getId());
    		obj.put("runToDate", itr.getEndDateTime().toString());
    		ja.put(obj);
    	}
    		
    	return ja.toString();
    }
    
    
  • Vishal Apr 12, 2016 @ 2:14

    Sorry for my so many questions below but I have been reading all your blog posts for "unit testing Rest API" so my apology for your time you may have to put in providing your comments.

    So you mentioned in the beginning of this document that "previous" Rest API test cases used assertions in lengthy way and we can write more readable test cases using "jsonPath". I have been reading all your great blog post on writing unit test cases of REST API and I did go through those "previous" blog posts too. However, my confusion is that there also you used "jsonPath" only so whats the difference when you say "that" was not readable and test cases in this blog readable. I have used so many this and that so let me paste you the link I am talking about:

    http://www.petrikainulainen.net/programming/spring-framework/unit-testing-of-spring-mvc-controllers-rest-api/
    I followed the above link first and wrote unit test cases. Then I read this blog post too.

    My SECOND confusion: I am following the "standalone" way of writing unit test cases of my Rest APIs. There you used MessageSource() and ExceptionResolver() methods. My structure of RestAPI is simple in a way that it does not have any UI, Servlet or other layers. Mine is raw API that will be used by Jenkins Jobs to pull and load database from one AWS resource to another AWS resource. I think I don't really require these two methods and I can directly use this in my setup method of unit test class:
    mockMvc = MockMvcBuilders.standaloneSetup(new TodoController(todoServiceMock)).build();
    Is that assumption correct?

    3rd and last QUESTION: One of your blog posts talks about "testing Spring Data JPA". I am using "Spring Boot" with CRUDRepository() that already provide me tailor made DB interaction methods like save(), find() etc. Do I still need to write test cases for my DAO class that acts as an interface and extends CRUDRespository()

    Again, Thanks a ton for your answers.

    • Petri Apr 13, 2016 @ 19:20

      Hi Vishal,

      I have been reading all your great blog post on writing unit test cases of REST API and I did go through those “previous” blog posts too. However, my confusion is that there also you used “jsonPath” only so whats the difference when you say “that” was not readable and test cases in this blog readable.

      The blog post that helps you to write unit tests for a REST API was written after this blog post. This blog post was published 16th of May, 2013. The linked blog post was published 26th of July, 2013.

      I think I don’t really require these two methods and I can directly use this in my setup method of unit test class: mockMvc = MockMvcBuilders.standaloneSetup(new TodoController(todoServiceMock)).build();
      Is that assumption correct?

      Yes. Nowadays I use this approach as well when I am writing unit tests for Spring controllers.

      Do I still need to write test cases for my DAO class that acts as an interface and extends CRUDRespository()

      Well, I think that it doesn't make a lot of sense to write integration tests for methods that are provided by Spring Data JPA. However, if you have added custom queries into your repository interface, you might want to test them. I have actually written a small tutorial that talks about writing tests for data access code. You might want to check it out.

  • Ashok Nov 9, 2017 @ 8:43

    This method is from my controller. Can you please explain that corresponding possible test cases in junit using mockito?

    @PutMapping("/countries/updateApprovalStatus")
    @Timed
    public ResponseEntity updateApprovalStatus(@RequestBody Map map, @RequestHeader HttpHeaders headers) throws URISyntaxException {
    log.debug("REST request to update approvalStatus for given Country ids : {}", map.get("ids"));

    String makerOrChecker=!headers.get("userType").isEmpty() && !headers.get("userType").get(0).isEmpty() && headers.get("userType").get(0).equals("maker") ? "maker":"checker";
    String approvalStatus = (String)map.get("approval_status");
    String comment = (String)map.get("comment");
    List idList = (List)map.get("ids");
    List ids = idList.stream().map(Long::valueOf).collect(Collectors.toList());

    countryService.updateApprovalStatus(ids,approvalStatus,makerOrChecker,comment);
    return ResponseEntity.ok().headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, idList.toString())).build();
    }

  • Keith Mar 22, 2018 @ 16:01

    Thanks for that. Was very helpful for me in getting my tests running

    • Petri Mar 23, 2018 @ 9:52

      You are welcome! It's good to hear that this blog post was useful to you.

  • Albert Nov 13, 2018 @ 14:17

    This is a great post with Spring. Before putting the JSON path into the assertion in "mockMvc. andExpect", you can validate the path online first here : https://jsonpath.herokuapp.com/.

  • Osipov Nov 13, 2018 @ 14:20

    Nice post for Json Jayway path. Also you can use the "declarative JSON DSL steps for java" which uses JSON Paths for API testing, handy for REST APIs and SOAP etc, bit easy to write tests over JUnit.

Leave a Reply