Tuesday, October 13, 2015

spring boot, mockito, spring rest, junit

This is sample code to do junit test for spring rest/spring boot with mockito.

package com.demo.app.web.api.v1;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
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.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.demo.app.WebApplication;
import com.demo.app.repository.entity.Stock;
import com.demo.app.service.StockService;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = { WebApplication.class })
public class StockControllerTest {

private static final MediaType APP_ContentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));

private MockMvc mvc;

@Mock
private StockService stockService;

@InjectMocks
private StockController controller;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller).build();
}

@After
public void tearDown() throws Exception {
}

@Test
public void testStocks() throws Throwable {

// prepare test data
List<Stock> stocks = new ArrayList<Stock>();
// stock1
Stock stock1 = new Stock();
stock1.setStockCode("code 1");
stock1.setStockName("name 1");
stock1.setStockPrice(1.111);
stock1.setStockPriceChange(-0.111);
stocks.add(stock1);
// stock2
Stock stock2 = new Stock();
stock2.setStockCode("code 2");
stock2.setStockName("name 2");
stock2.setStockPrice(2.222);
stock2.setStockPriceChange(-0.222);
stocks.add(stock2);
// stock3
Stock stock3 = new Stock();
stock3.setStockCode("code 3");
stock3.setStockName("name 3");
stock3.setStockPrice(3.333);
stock3.setStockPriceChange(-0.333);
stocks.add(stock3);

Mockito.when(stockService.findAll()).thenReturn(stocks);

mvc.perform(get("/api/v1/stocks")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType)).andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$[0].stockCode", is(stock1.getStockCode())))
.andExpect(jsonPath("$[0].stockName", is(stock1.getStockName())))
.andExpect(jsonPath("$[0].stockPrice", is(stock1.getStockPrice())))
.andExpect(jsonPath("$[0].stockPriceChange", is(stock1.getStockPriceChange())))
.andExpect(jsonPath("$[1].stockCode", is(stock2.getStockCode())))
.andExpect(jsonPath("$[1].stockName", is(stock2.getStockName())))
.andExpect(jsonPath("$[1].stockPrice", is(stock2.getStockPrice())))
.andExpect(jsonPath("$[1].stockPriceChange", is(stock2.getStockPriceChange())))
.andExpect(jsonPath("$[2].stockCode", is(stock3.getStockCode())))
.andExpect(jsonPath("$[2].stockName", is(stock3.getStockName())))
.andExpect(jsonPath("$[2].stockPrice", is(stock3.getStockPrice())))
.andExpect(jsonPath("$[2].stockPriceChange", is(stock3.getStockPriceChange())));

}

@Test
public void testGetStock() throws Throwable {

// prepare test data
Stock stock = new Stock();
stock.setStockCode("abc");
stock.setStockName("name 1");
stock.setStockPrice(1.111);
stock.setStockPriceChange(-0.111);

Mockito.when(stockService.findByStockCode(stock.getStockCode())).thenReturn(stock);

mvc.perform(get("/api/v1/stocks/{code}", stock.getStockCode())).andDo(print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(content().contentTypeCompatibleWith(APP_ContentType))
.andExpect(jsonPath("$.stockCode", is(stock.getStockCode())))
.andExpect(jsonPath("$.stockName", is(stock.getStockName())))
.andExpect(jsonPath("$.stockPrice", is(stock.getStockPrice())))
.andExpect(jsonPath("$.stockPriceChange", is(stock.getStockPriceChange())));
}

}


=================== ==========================
with eclipse, if encounter this exception as follows,

java.lang.SecurityException: class "org.hamcrest.Matchers"'s signer information does not match signer information of other classes in the same package

open "Configure Build Path" and select "Library" tab, remove "Junit" from the build path. The root cause is jar conflict with plug in "Hamctest" inside eclipse.