Saturday, 13 September 2014

Spring MVC Test cases with Annotated Beans Using Mockito

Annotations make java developer's life easy and also it feels like annotation based classes are complex for unit testing. But in reality it is quite simple. There are couple of ways through which you can test autowired/spring based classes.

Method 1:
You can use AnnotationConfigApplicationContext to load application context. Instantiate application context, register annotated classes and test your methods. Here is the sample code

package com.bala.controller;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.bala.service.ArticleService;
public class ArticleControllerSpringUtils {
private AnnotationConfigApplicationContext appCtx;
@Before
public void initializeAnnotationContext() {
appCtx = new AnnotationConfigApplicationContext();
}
@Test
public void testSampleMethod() {
initializeAnnotationContext();
appCtx.register(ArticleService.class);
appCtx.register(ArticleController.class);
appCtx.refresh();
ArticleController articleController = appCtx
.getBean(ArticleController.class);
System.out.println(articleController.getAll());
}
}
Method 2:
Even though preceding method is an easiest way to test annotation based spring classes, if your test case becomes complex and if you want to mock actual request etc, you better move to mocking framework instead of basic one. I have used mockito with spring-test to mock actual requests with spring beans. Here is the sample code

package com.bala.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.bala.domain.Article;
import com.bala.service.ArticleService;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("/spring/rest-servlet.xml")
public class ArticleControllerTest {
private final static Logger logger = LoggerFactory
.getLogger(ArticleControllerTest.class);
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@InjectMocks
private ArticleController articleControllerTest;
// TODO Spy all the beans if you want to mock them otherwise use @Mock
@Spy
private ArticleService articleService;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
MockitoAnnotations.initMocks(this);
}
@Test
public void getAll() throws Exception {
System.out.println(articleControllerTest.getAll());
}
@Test
public void getAllByMockingRequest() throws Exception {
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.get("/article/").accept(
MediaType.APPLICATION_JSON)).andReturn();
logger.info(result.getResponse().getContentAsString());
}
@Test
public void getArticleByMockingRequest() throws Exception {
String articleId = "1";
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.get("/article/" + articleId).accept(
MediaType.APPLICATION_JSON)).andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void putArticleByMockingRequest() throws Exception {
String articleId = "1";
Article article = new Article("1", "Test", "Sample Aticle");
ObjectMapper mapper = new ObjectMapper();
byte[] content = mapper.writeValueAsBytes(article);
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.put("/article/" + articleId)
.accept(MediaType.APPLICATION_JSON).content(content))
.andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void postArticleByMockingRequest() throws Exception {
Article article = new Article("1", "Test", "Sample Aticle");
ObjectMapper mapper = new ObjectMapper();
byte[] content = mapper.writeValueAsBytes(article);
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.post("/article/")
.accept(MediaType.APPLICATION_JSON).content(content))
.andReturn();
System.out.println(result.getResponse().getContentAsString());
}
@Test
public void deleteArticleByMockingRequest() throws Exception {
String articleId = "1";
MvcResult result = this.mockMvc.perform(
MockMvcRequestBuilders.delete("/article/" + articleId).accept(
MediaType.APPLICATION_JSON)).andReturn();
System.out.println(result.getResponse().getContentAsString());
}
}
In the above sample code we have used spy to mock real objects, if you just want to mock it you can use mock annotation instead of spy.

For this you need mockito and spring-test jars. Following are the minimal poms for the both respectively.
     <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
  </dependency>
            <dependency>
           <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.0.0.RELEASE</version>
          <scope>test</scope>
  </dependency>

Here is the complete code with both the testing methodologies.
spring-test-template using mockito

No comments:

Post a Comment