Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Friday, December 12, 2014

Spring Web: Get current request and generate base URL

Just a simple way to generate application's base URL according to the environment context using current request:


protected static String getBaseEnvLinkURL() {

   String baseEnvLinkURL=null;
   HttpServletRequest currentRequest =
      ((ServletRequestAttributes)RequestContextHolder.
       currentRequestAttributes()).getRequest();
   // lazy about determining protocol but can be done too
   baseEnvLinkURL = "http://" + currentRequest.getLocalName();
   if(currentRequest.getLocalPort() != 80) {
      baseEnvLinkURL += ":" + currentRequest.getLocalPort();
   }
   if(!StringUtils.isEmpty(currentRequest.getContextPath())) {
      baseEnvLinkURL += currentRequest.getContextPath();
   }            
   return baseEnvLinkURL;
}

Tuesday, July 22, 2014

Spring: Integration testing under Spring Boot application context but mocking services


Use @MockBean annotation

DEPRACATED:

So I wanted to create some integration tests for an API application that uses Spring Boot. The thing is that I needed to load the same application context as the real applicationm, because Spring Boot performs a bunch of configurations for you, and these were not being loaded in a StandAlone mode.

But also I didn't want to use real services which depend upon real data. Depending on databases for your tests creates fragile tests.

After researching on the web I found this way:


This is the typical Spring-Boot entry point class.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

A base class having the logic to init the application context.

import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = MyApplication.class)
public abstract class BaseIntegrationTest {

    protected MockMvc mockMvc;
    
    @Autowired
    protected WebApplicationContext wac;

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

An implementation class mocking a required service class.
public class FooIntegrationTest extends BaseIntegrationTest {

    @Configuration
    public static class TestConfiguration {
        @Bean
        @Primary
        public FooService fooService() {
            return mock(FooService.class);
        }
    }


    @Autowired
    FooService mockFooService;
}

Wednesday, May 1, 2013

Spring Jackson library example to consume JSON returned by REST service


A brief example of how to use the Spring Jackson library to consume a JSON returned by a REST service. The class below is a Singleton that initializes the RestTemple one time only.

import java.util.ArrayList;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

public class RestJsonTest {
 
 private static RestJsonTest instance;
 private RestTemplate restTemplate;
 private String url ="http://rest.service.url";
 
 public static RestJsonTest getInstance() {
  if (instance == null) {
   instance = new RestJsonTest();
  }
  return instance;
 }
 
 private RestJsonTest() {
  // Setup the RestTemplate configuration.
  restTemplate = new RestTemplate();
  restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
  List<HttpMessageConverter<?>> messageConverterList = restTemplate.getMessageConverters();
  
  // Set HTTP Message converter using a JSON implementation.
  MappingJacksonHttpMessageConverter jsonMessageConverter = new MappingJacksonHttpMessageConverter();
  
  // Add supported media type returned by BI API.
  List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
  supportedMediaTypes.add(new MediaType("text", "plain"));
  supportedMediaTypes.add(new MediaType("application", "json"));
  jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
  messageConverterList.add(jsonMessageConverter);
  restTemplate.setMessageConverters(messageConverterList);
 }
 
 public SearchResults searchResults() {
  return restTemplate.getForObject(url, SearchResults.class);  
 }
 
 public static void main(String[] args) {
  RestJsonTest jsonTest = RestJsonTest.getInstance();
  SearchResults results = jsonTest.searchResults();
 }
}

The mapping of the JSON to Java classes can be done via annotations like it's shown here:
package com.bodybuilding.api.commerce.clientservice;

import java.util.List;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;


/**
 *{
 * "search_keywords":"Social Networks",
 *  "total_time":200,
 *  "results":{
 *   "result_01":{
 *    "url":"http://www.facebook.com",
 *    "rank": "1"
 *   },
 *   "result_02":{
 *   "url":"http://www.twitter.com",
 *    "rank": "2"
 *   }
 *  }
 * }
 */
@JsonIgnoreProperties(ignoreUnknown=true)
public class SearchResults {
 
 @JsonProperty("search_keywords")
 private String keywords;
 
 @JsonProperty("total_time")
 private long totalTime;
 
 @JsonProperty("results")
 private List<SearchResult> results;
 
 public String getKeywords() {
  return keywords;
 }
 public void setKeywords(String keywords) {
  this.keywords = keywords;
 }
 public long getTotalTime() {
  return totalTime;
 }
 public void setTotalTime(long totalTime) {
  this.totalTime = totalTime;
 }
 public List<SearchResult> getResults() {
  return results;
 }
 public void setResults(List<SearchResult> results) {
  this.results = results;
 } 
}

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown=true)
public class SearchResult {
 
 @JsonProperty("url")
 private String url;
 
 @JsonProperty("rank")
 private int rank;
 
 public String getUrl() {
  return url;
 }
 public void setUrl(String url) {
  this.url = url;
 }
 public int getRank() {
  return rank;
 }
 public void setRank(int rank) {
  this.rank = rank;
 }
}

The RestTemplate bean can be also configure with Spring injection:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
     <property name="requestFactory">
      <bean id="clientHttpRequestFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory" />   
     </property>
     <property name="messageConverters">
      <list>
       <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes">
         <list>
          <bean id="jsonMediaTypeTextPlain" class="org.springframework.http.MediaType">
           <constructor-arg value="text"/>
          <constructor-arg value="plain"/>
          </bean>
          <bean id="jsonMediaTypeApplicationJson" class="org.springframework.http.MediaType">
           <constructor-arg value="application"/>
          <constructor-arg value="json"/>
          </bean>
         </list>
        </property>
       </bean>
      </list>
     </property>  
</bean>