Unit Test (Java Spring)
Pre-Action
Install J Unit and Mockito dependencies
E.g: Maven
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.0</version>
<scope>test</scope>
</dependency>
Stub vs Mock vs Spy
Stub vs Mock
Stub: Initialize -> Exercise -> Verify
private class FooStub implements Foo
{
public String bar()
{
return"baz";
}
}
public class FooCollectionTest
{
@Test
public void test()
{
//Initialize
FooStub newFooStub = new FooStub();
FooCollection sut = newFooCollection();
sut.add(newFooStub.bar());
sut.add(newFooStub.bar());
//Exercise and Verify
assertEquals("bazbaz",sut.joined());
}
}
Mock: Initialize -> Set up expectations -> Exercise -> Verify
public class FooCollectionTest
{
@Mock
FooStub newFooStub;
//Initialize
@InjectMock
FooCollection sut ;
@Test
public void test()
{
// Setup expectations
Mockito.doReturn("baz").when(newFooStub).bar();
sut.add(newFooStub.bar());
sut.add(newFooStub.bar());
//Exercise and Verify
assertEquals("bazbaz",sut.joined());
}
}
Mock vs Spy
Spy will actually call the real method of the class , while mock doesn't
Spy
@Test
public void whenCreateSpy_thenCreate() {
List spyList = Mockito.spy(new ArrayList());
spyList.add("one");
Mockito.verify(spyList).add("one");
assertEquals(1, spyList.size());
}
Mock
@Test
public void whenCreateMock_thenCreated() {
List mockedList = Mockito.mock(ArrayList.class);
mockedList.add("one");
Mockito.verify(mockedList).add("one");
assertEquals(0, mockedList.size());
}
Mockito Method
doAnswer (used to mock the void type function)
Mockito.doAnswer(invocation->{
if(invocation != null && invocation.getArguments().length > 0){
System.out.println("Test Void");
}
return null;
}).when(productService).test(Integer input);
doReturn (used to mock the return value of function)
Mockito.doReturn(0).when(shopService).test(any(Integer.class));
Service Testing Example
TestServiceImpl
package com.example.demo.service.impl;
import com.example.demo.service.ShopService;
import com.example.demo.service.TestService;
public class TestServiceImpl implements TestService {
Integer addNumber = 2;
ShopService shopService;
@Override
public Integer gg(){
return 3;
}
@Override
public void testVoid(){
}
@Override
public Integer test(){
Integer num = gg();
Integer num2 = shopService.test(10);
return 1 + num + num2;
}
}
ShopServiceImpl
package com.example.demo.service.impl;
import com.example.demo.service.ShopService;
public class ShopServiceImpl implements ShopService {
@Override
public Integer test(Integer input){
return input;
}
}
testServiceTest
package com.example.demo.service;
import com.example.demo.service.impl.TestServiceImpl;
import org.junit.Assert;
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.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.any;
@RunWith(MockitoJUnitRunner.class)
public class testServiceTest {
@Mock
private ShopService shopService;
@InjectMocks
private TestService testService;
private TestService testService1;
//Constructor
public testServiceTest() {
testService = new TestServiceImpl();
}
@Before
public void setUp() throws Exception{
testService1 = Mockito.spy(testService);
}
@Test
public void testTest() throws Exception{
Mockito.when(testService1.gg()).thenReturn(1);
Mockito.doReturn(0).when(shopService).test(any(Integer.class));
Mockito.doAnswer(invocationOnMock -> {
if(invocationOnMock != null && invocationOnMock.getArguments().length>0){
System.out.println("testvoid");
}
return null;
}).when(testService1).testVoid();
Integer result = testService1.test();
Assert.assertSame(2,result);
}
}
Controller Unit Test
MockMvc
Create a new MockMvc Object as a entry point, so that we can use it to call the link of API
@RunWith(MockitoJUnitRunner.class)
public class schoolControllerTest
{
private MockMvc mockMvc;
private SchoolController schoolController;
@Before
public void setUp() throws NotFoundException{
this.mockMvc = MockMvcBuilders.standaloneSetup(schoolController).build();
}
}
Method
@Test
public void testView() throws Exception {
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/user/1"))
.andExpect(MockMvcResultMatchers.view().name("user/view"))
.andExpect(MockMvcResultMatchers.model().attributeExists("user"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
perform: make a request to api end point
andExpect: verify the result whether the actual is equal to actual or not
andDo: to make a handling after getting the result, such as print out the response
andReturn: return back to MvcResult
MockMvcRequestBuilders
Used to create a request
Methods
MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L);
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get类似,但是是POST方法;
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get类似,但是是PUT方法;
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get类似,但是是DELETE方法;
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get类似,但是是OPTIONS方法;
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables): 提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder;
RequestBuilder asyncDispatch(final MvcResult mvcResult):创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;
MockMvcResultMatchers
used to match the result of api end point , such as content-type, https status, return value
Methods
HandlerResultMatchers handler():请求的Handler验证器,比如验证处理器类型/方法名;此处的Handler其实就是处理请求的控制器;
RequestResultMatchers request():得到RequestResultMatchers验证器;
ModelResultMatchers model():得到模型验证器;
ViewResultMatchers view():得到视图验证器;
FlashAttributeResultMatchers flash():得到Flash属性验证;
StatusResultMatchers status():得到响应状态验证器;
HeaderResultMatchers header():得到响应Header验证器;
CookieResultMatchers cookie():得到响应Cookie验证器;
ContentResultMatchers content():得到响应内容验证器;
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath (String expression, Matcher matcher):得到Json表达式验证器;
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args):得到Xpath表达式验证器;
ResultMatcher forwardedUrl(final String expectedUrl):验证处理完请求后转发的url(绝对匹配);
ResultMatcher forwardedUrlPattern(final String urlPattern):验证处理完请求后转发的url(Ant风格模式匹配,@since spring4);
ResultMatcher redirectedUrl(final String expectedUrl):验证处理完请求后重定向的url(绝对匹配);
ResultMatcher redirectedUrlPattern(final String expectedUrl):验证处理完请求后重定向的url(Ant风格模式匹配,@since spring4)
MockMvcResultHandlers
used to print the whole of the response of api end point
Example
@Test
public void getInventoryByProductCodeTest1() throws Exception
{
mockMvc.perform(MockMvcRequestBuilders.get("/api/getSchool"))
.andExpect(MockMvcResultMatchers.status().isOk()) // Check the http status
.andExpect(MockMvcResultMatchers.content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) // check the content type
.andExpect(MockMvcResultMatchers.jsonPath("studentName").value("Tom")); // check the result
}
Reference
Last updated
Was this helpful?