400+ Java Interview Questions and Answers blog |
Unit testing Spring MVC controllers for web and RESTful services with spring-test-mvc Posted: 12 Dec 2012 04:20 PM PST
Step 1: You need to have the right third-party libraries. The key ones to take note are spring-test-mvc, spring-test, json-path, hamcrest-library, hamcrest-core, and mockito-core. <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-library</artifactId> <version>1.3</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.8</version> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.2.6</version> <scope>runtime</scope> </dependency> <!-- JSON XPATH library --> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>0.5.6</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>org.springframework.context</artifactId> <version>3.1.0.RELEASE</version> <exclusions> <!-- Exclude Commons Logging in favour of SLF4j --> <exclusion> <groupId>org.apache.commons</groupId> <artifactId>com.springsource.org.apache.commons.logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>3.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>3.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>3.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>3.1.0.RELEASE</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> <!-- for tspring testing --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test-mvc</artifactId> <version>1.0.0.M1</version> </dependency>Step 2: The next step is to define a Spring MVC controller that we will be writing unit test for. package com.myapp.accounting.aes.securities.pricehistory.controller; import java.sql.SQLException; import java.util.Date; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.HttpStatus; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.security.authentication.LockedException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import com.jpmorgan.accounting.aes.securities.pricehistory.model.PriceHistory; import com.jpmorgan.accounting.aes.securities.pricehistory.service.PriceHistoryService; import com.jpmorgan.accounting.dm.model.refdata.securities.MarketDataSecurityPriceHist; @Controller public class PriceHistoryController { /** * Service for accessing the Market Data repository. Contains the business logic. */ @Resource(name = "aes_priceHistoryService") private PriceHistoryService securityPriceService; @RequestMapping(value = "/pricehistory", method = RequestMethod.GET) @ResponseBody public List<MarketDataSecurityPriceHist> getPriceHistory(@RequestParam(value="latestUpdatedTimeStamp", required=true) @DateTimeFormat(pattern="dd MMM yyyy HH:mm:ss") Date latestUpdatedTimeStamp, @RequestParam(value="maxRecords", required=false, defaultValue="100") int maxRecords) throws Exception { // call the business service PriceHistory result = securityPriceService.getPriceHistory(maxRecords, latestUpdatedTimeStamp); return result.getHistory(); } } Step 3: The PriceHistory object that holds a list of "MarketDataSecurityPriceHist" objects. package com.myapp.accounting.aes.securities.pricehistory.model; import com.myapp.accounting.dm.model.refdata.securities.MarketDataSecurityPriceHist; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class PriceHistory implements Serializable { private static final long serialVersionUID = 1L; private List Step 4: Define the MarketDataSecurityPriceHist class that holds the relevant attributes. package com.myapp.accounting.dm.model.refdata.securities; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; import javax.persistence.Entity; import javax.xml.bind.annotation.XmlElement; @Entity //persistence entity public class MarketDataSecurityPriceHist implements Serializable { private static final long serialVersionUID = 1444498748039607997L; private String securityCd; private Date priceDttm; private BigDecimal bidPrice; private BigDecimal closePrice; private BigDecimal lastPrice; private BigDecimal askPrice; private String lastUpdatedAction; private String LastUpdatedDetailUser; private Date lastUpdatedTimeStamp; private Date loadTimeStamp; private String pricecondition; private String recordType; private String priceTime; private String source; public MarketDataSecurityPriceHist() {} @XmlElement public String getSecurityCd() { return securityCd; } public void setSecurityCd(String securityCd) { this.securityCd = securityCd; } @XmlElement public Date getPriceDttm() { return priceDttm; } public void setPriceDttm(Date priceDttm) { this.priceDttm = priceDttm; } @XmlElement public BigDecimal getBidPrice() { return bidPrice; } public void setBidPrice(BigDecimal bidPrice) { this.bidPrice = bidPrice; } //other setters and getters are omitted }Step 5: Finally, and most importantly the unit test class that uses mockito to mock the PriceHistoryService implementation and spring-test-mvc to mock the controller that returns a json response. package com.myapp.accounting.aes.securities.pricehistory; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.test.web.server.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.server.setup.MockMvcBuilders.standaloneSetup; import static org.springframework.test.web.server.result.MockMvcResultMatchers.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.http.MediaType; import com.myapp.accounting.aes.securities.pricehistory.controller.PriceHistoryController; import com.myapp.accounting.aes.securities.pricehistory.model.PriceHistory; import com.myapp.accounting.aes.securities.pricehistory.service.PriceHistoryService; import com.myapp.accounting.aes.securities.pricehistory.service.impl.PriceHistoryServiceImpl; import com.myapp.accounting.dm.model.refdata.securities.MarketDataSecurityPriceHist; public class PriceHistoryController2Test { private PriceHistoryService mockSecurityPriceService; private PriceHistoryController controller; @Before public void setup() { controller = new PriceHistoryController(); mockSecurityPriceService = mock(PriceHistoryServiceImpl.class); controller.setSecurityPriceService(mockSecurityPriceService); } @Test public void getPriceHistory() throws Exception { when( mockSecurityPriceService.getPriceHistory( (Integer) Mockito.any(), (Date) Mockito.any())) .thenReturn(getPriceHistoryTestData()); standaloneSetup(controller) .build() .perform( get( "/pricehistory?latestUpdatedTimeStamp=26 Jul 211 12:00:00&maxRecords=3000") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().type("application/json")) .andExpect(jsonPath("$.[0].securityCd").value("test")) .andExpect(jsonPath("$.[0].bidPrice").value(12.50)) .andExpect(jsonPath("$.[0].closePrice").value(12.50)); } //mock data that gets returned when getPriceHistory(...) method is called private static PriceHistory getPriceHistoryTestData() { PriceHistory ph = new PriceHistory(); List<marketdatasecuritypricehist> history = new ArrayList<marketdatasecuritypricehist>(); MarketDataSecurityPriceHist md = new MarketDataSecurityPriceHist(); md.setSecurityCd("test"); BigDecimal price = new BigDecimal("12.50"); md.setAskPrice(price); md.setBidPrice(price); md.setClosePrice(price); md.setLastUpdatedAction("SOME_ACTION"); md.setRecordType("RECORD_TYPE"); md.setLastUpdatedDetailUser("tesr"); Calendar cal = Calendar.getInstance(); cal.set(2010, 01, 01, 00, 00, 00); Date date = cal.getTime(); md.setLastUpdatedTimeStamp(date); md.setPriceDttm(date); System.out.println(date); history.add(md); ph.setHistory(history); return ph; } } That's all to it for testing an MVC controller. The URL for above JSON RESTful web service will be something like http://localhost:8080/accounting-server/securities/pricehistory?latestUpdatedTimeStamp=26+Jul+2010+12:00:00&maxRecords=3000 and the JSON data returned will be something like [{"securityCd":"XX123","priceDttm":"2012-01-28","bidPrice":125.50,"closePrice":126.60,"lastPrice":124.50,"askPrice":123.80,"lastUpdatedAction":"NO ACTION","lastUpdatedTimeStamp":1327705288015,"loadTimeStamp":88150,"pricecondition":"NO_CONDITION","recordType":null,"priceTime":"10:01:28.150 AM","source":"HiPort","lastUpdatedDetailUser":"arul"}, {"securityCd":"YY321","priceDttm":"2012-01-28","bidPrice":125.50,"closePrice":126.60,"lastPrice":124.50,"askPrice":123.80,"lastUpdatedAction":"NO ACTION","lastUpdatedTimeStamp":1327705288015,"loadTimeStamp":88150,"pricecondition":"NO_CONDITION","recordType":null,"priceTime":"10:01:28.150 AM","source":"HiPort","lastUpdatedDetailUser":"arul"}] |
You are subscribed to email updates from 400+ Java Interview Questions and Answers blog To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Google Inc., 20 West Kinzie, Chicago IL USA 60610 |
Post a Comment