Mockito 是一个模拟测试框架,主要功能是在单元测试中模拟类/对象的行为。
Mock可以理解为创建一个虚假的对象,或者说模拟出一个对象.在测试环境中用来替换掉真实的对象,以达到我们可以
根据 JUnit 单测隔离 ,当 Mockito 和 JUnit 配合使用时,也会将非static变量或者非单例隔离开。
比如使用 @Mock 修饰的 mock 对象在不同的单测中会被隔离开。
mock方法来自org.mockito.Mock
,它标识可以mock一个对象或者是接口
public static <T> mock(Class<T> classToMock);
入参:classToMock: 待mock对象的class类
返回:mock出来的类的对象(此时对象内依旧无数据)
Random random = Mockito.mock(Random.class);
when(random.nextBoolean()).thenReturn(true);
logger.info("result: {}", random.nextBoolean());//result: true
注:
QueryFactory#query
为静态方法
/**
* 静态类 T、静态方法的 Mock
* 1、mock方式: MockedStatic<T> mockClass = mockStatic(T.class); mockClass.when(...).thenReturn(...)
* 2、静态类/静态方法需在多个测试用例中 mock 时,需使用: `try-with-resources`的方式,以解决此问题"To create a new mock, the existing static mock registration must be deregistered"
*/
try(MockedStatic<QueryFactory> mockedQueryFactory = Mockito.mockStatic(QueryFactory.class)){
mockedQueryFactory.when( () -> QueryFactory.query(any(), any(), any(), any()) ).thenReturn(result);
signalNamesMappingCacheService.init();
try {
commonSearchBizSevice.executeQuery(requestInfo);//内部将调用 QueryFactory.query(...)
} catch (Exception e) {
logger.info("happens a exception: SUCCESS");//内置脚本反射调用失败
}
}
存根的意思就是给mock对象规定一行的行为,使其按照我们的要求来执行具体的动作。
demo1
//You can mock concrete classes, not just interfaces
LinkedList mockedList = mock(LinkedList.class);
//stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(0)).thenReturn("two");
when(mockedList.get(1)).thenThrow(new RuntimeException());
//following prints "two"
System.out.println(mockedList.get(0));
//following throws runtime exception
System.out.println(mockedList.get(1));
//following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
//Although it is possible to verify a stubbed invocation, usually it's just redundant
//If your code cares what get(0) returns, then something else breaks (often even before verify() gets executed).
//If your code doesn't care what get(0) returns, then it should not be stubbed.
verify(mockedList).get(0);
demo2
@Test
public void test(){
// 创建Mock对象,参数可以是类或者接口
List<String> list = mock(List.class);
// 设置方法的预期返回值
when(list.get(0)).thenReturn("zuozewei");
when(list.get(1)).thenThrow(new RuntimeException("test exception"));
String result = list.get(0);
// 验证方法调用
verify(list).get(0);
//断言,list的第一个元素是否是 "zuozwei"
Assert.assertEquals(result,"zuozewei");
}
mock实例对象的常用方法
mock类对象的常用方法
mockStaticObject.when(Verification verification).thenReturn(…)
MockedStatic
mockedQueryFactory.when( () -> QueryFactory.query(any(), any(), any(), any()) ).thenReturn(result);
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import static org.mockito.Mockito.*;
public class MockitoDemo {
@Test
public void test() {
List mockList = mock(List.class);Assert.assertEquals(0, mockList.size());
Assert.assertEquals(null, mockList.get(0));
mockList.add("a"); // 调用 mock 对象的写方法,是没有效果的
Assert.assertEquals(0, mockList.size()); // 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(0)); // 没有指定 get(0) 返回值,这里结果是默认值
when(mockList.get(0)).thenReturn("a"); // 指定 get(0)时返回 a
Assert.assertEquals(0, mockList.size()); // 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals("a", mockList.get(0)); // 因为上面指定了 get(0) 返回 a,所以这里会返回 a
Assert.assertEquals(null, mockList.get(1)); // 没有指定 get(1) 返回值,这里结果是默认值
// 参数匹配:精确匹配
when(mockStringList.get(0)).thenReturn("a");
when(mockStringList.get(1)).thenReturn("b");
Assert.assertEquals("a", mockStringList.get(0));
Assert.assertEquals("b", mockStringList.get(1));
// 参数匹配:模糊匹配
when(mockStringList.get(anyInt())).thenReturn("a"); // 使用 Mockito.anyInt() 匹配所有的 int
Assert.assertEquals("a", mockStringList.get(0));
Assert.assertEquals("a", mockStringList.get(1));
}
//eq(...)
@Test
public void test2(){
...
when(databaseConnectionManager.borrowConnector(eq(DsType2.INFLUXDB), eq(dataSource), any(Integer.class))).thenReturn(connector);
...
}
}
import org.junit.Assert;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class MockitoDemo {
static class ExampleService {
public int add(int a, int b) {
return a+b;
}
}
@Test
public void test() {
ExampleService exampleService = mock(ExampleService.class);
// mock 对象方法的默认返回值是返回类型的默认值
Assert.assertEquals(0, exampleService.add(1, 2));
// 设置让 add(1,2) 返回 100
when(exampleService.add(1, 2)).thenReturn(100);
Assert.assertEquals(100, exampleService.add(1, 2));
// 重置 mock 对象,add(1,2) 返回 0
reset(exampleService);
Assert.assertEquals(0, exampleService.add(1, 2));
}
@Test
public void test2() {
ExampleService exampleService = spy(new ExampleService());
// spy 对象方法调用会用真实方法,所以这里返回 3
Assert.assertEquals(3, exampleService.add(1, 2));
// 设置让 add(1,2) 返回 100
when(exampleService.add(1, 2)).thenReturn(100);
Assert.assertEquals(100, exampleService.add(1, 2));
// 重置 spy 对象,add(1,2) 返回 3
reset(exampleService);
Assert.assertEquals(3, exampleService.add(1, 2));
}
}
@mock快速创建mock的方法,使用
@mock注解需要搭配MockitoAnnotations.openMocks(testClass)方法一起使用.
public class ArticleManagerTest {
@Mock
private ArticleCalculator calculator;
@Mock
private ArticleDatabase database;
@Mock
private UserProvider userProvider;
private ArticleManager manager;
@org.junit.jupiter.api.Test
void testSomethingInJunit5() {
// 初始化mock对象
MockitoAnnotations.openMocks(testClass);
//Mockito.mock(class);
Mockito.spy(class);
}
// 简化
// @BeforeEach
// void setUp() {
// MockitoAnnotations.openMocks(this);
// }
}
spy 和 mock不同,不同点是:
@Spy注解需要搭配MockitoAnnotations.openMocks(testClass)
方法一起使用.
import org.junit.Assert;
import org.junit.Test;
import static org.mockito.Mockito.*;
class ExampleService {
int add(int a, int b) {
return a+b;
}
}
public class MockitoDemo {
// 测试 spy
@Test
public void test_spy() {
ExampleService spyExampleService = spy(new ExampleService());
// 默认会走真实方法
Assert.assertEquals(3, spyExampleService.add(1, 2));
// 打桩后,不会走了
when(spyExampleService.add(1, 2)).thenReturn(10);
Assert.assertEquals(10, spyExampleService.add(1, 2));
// 但是参数比匹配的调用,依然走真实方法
Assert.assertEquals(3, spyExampleService.add(2, 1));
}
// 测试 mock
@Test
public void test_mock() {
ExampleService mockExampleService = mock(ExampleService.class);
// 默认返回结果是返回类型int的默认值
Assert.assertEquals(0, mockExampleService.add(1, 2));
}
}
import org.junit.Assert;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import static org.mockito.Mockito.*;
class ExampleService {
int add(int a, int b) {
return a+b;
}
}
public class MockitoDemo {
@Spy
private ExampleService spyExampleService;
@Test
public void test_spy() {
MockitoAnnotations.openMocks(this);
Assert.assertEquals(3, spyExampleService.add(1, 2));
when(spyExampleService.add(1, 2)).thenReturn(10);
Assert.assertEquals(10, spyExampleService.add(1, 2));
}
}
mockito 会将 @Mock、@Spy 修饰的对象自动注入到 @InjectMocks 修饰的对象中。
注入方式有多种,mockito 会按照下面的顺序尝试注入:
构造函数注入
设值函数注入(set函数)
属性注入
package demo;
import java.util.Random;
public class HttpService {
public int queryStatus() {
// 发起网络请求,提取返回结果
// 这里用随机数模拟结果
return new Random().nextInt(2);
}
}
package demo;
public class ExampleService {
private HttpService httpService;
public String hello() {
int status = httpService.queryStatus();
if (status == 0) {
return "你好";
}
else if (status == 1) {
return "Hello";
}
else {
return "未知状态";
}
}
}
import org.junit.Assert;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.when;
public class ExampleServiceTest {
@InjectMocks // 将httpService主动注入
private ExampleService exampleService = new ExampleService();
@Mock
private HttpService httpService;
@Test
public void test01() {
MockitoAnnotations.initMocks(this);
when(httpService.queryStatus()).thenReturn(0);
Assert.assertEquals("你好", exampleService.hello());
}
}
验证是校验待验证的对象是否发生过某些行为,Mockito中验证的方法是:verify
verify(mock).someMoethod("some arg");
verify(mock,times(100)).someMoethod("some arg");
使用verify验证(Junit的断言机制):
@Test
void check() {
Random random = Mockito.mock(Random.class);
System.out.println(random.nextInt());
Mockito.verify(random,Mockito.times(2)).nextInt();
}
Verify配合times()方法,可以校验某些操作发生的次数
//using mock
mockedList.add("once");
mockedList.add("twice");
mockedList.add("twice");
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
// 默认调用1次
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once");
// 自定义调用多次
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
// 从不调用
verify(mockedList, never()).add("never happened");
// atLeast()/atMost() 至少调用 / 之多调用
verify(mockedList, atMostOnce()).add("once");
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("three times");
verify(mockedList, atMost(5)).add("three times");
// 超时验证
verify(mock, timeout(100)).someMethod();
verify(mock, timeout(100).times(1)).someMethod();
//只要 someMethod() 在 100 毫秒内被调用 2 次,就会通过
verify(mock, timeout(100).times(2)).someMethod();
//someMethod() 至少在 100 毫秒内被调用 2 次,就会通过
verify(mock, timeout(100).atLeast(2)).someMethod();
对于前后端分离的项目而言,无法直接从前端静态代码中测试接口的正确性,因此可以通过MockMVC来模拟HTTP请求。基于RESTful风格的SpringMVC的测试,可以测试完整的Spring MVC流程,即从URL请求到控制器处理,再到视图渲染都可以测试。
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
//在每个测试方法执行之前都初始化MockMvc对象
@BeforeEach
public void setupMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
1 controller 层
/**
* id:\\d+只匹配数字
* @param id
* @return
*/
@GetMapping("/user/{id:\\d+}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}
2 Mockito构建自定义返回结果
userService.getById
并没有返回结果,但是我们的测试并不关心userService.getById这个方法是否正常,只是在我们的测试中需要用到这个方法,所以我们可以Mock掉UserService的getById方法,自己定义返回的结果。
@MockBean
private UserService userService;
@Test
void getUserById() throws Exception {
User user = new User();
user.setId(1);
user.setNickname("yunqing");
//Mock一个结果,当userService调用getById的时候,返回user
doReturn(user).when(userService).getById(any());
//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理
mockMvc.perform(MockMvcRequestBuilders
//构造一个get请求
.get("/user/1")
//请求类型 json
.contentType(MediaType.APPLICATION_JSON))
// 期望的结果状态 200
.andExpect(MockMvcResultMatchers.status().isOk())
//添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台
.andDo(MockMvcResultHandlers.print());
}
3 传参数
@Test
void getUserByUsername() throws Exception {
// perform : 执行请求 ;
mockMvc.perform(MockMvcRequestBuilders
//MockMvcRequestBuilders.get("/url") : 构造一个get请求
.get("/user/getUserByName")
//传参
.param("username","admin")
// 请求type : json
.contentType(MediaType.APPLICATION_JSON))
// 期望的结果状态 200
.andExpect(MockMvcResultMatchers.status().isOk());
}
4 期望返回结果集有两个元素
@Test
void getAll() throws Exception {
User user = new User();
user.setNickname("yunqing");
List<User> list = new LinkedList<>();
list.add(user);
list.add(user);
//Mock一个结果,当userService调用list的时候,返回user
when(userService.list()).thenReturn(list);
//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理
mockMvc.perform(MockMvcRequestBuilders
//构造一个get请求
.get("/user/list")
//请求类型 json
.contentType(MediaType.APPLICATION_JSON))
// 期望的结果状态 200
.andExpect(MockMvcResultMatchers.status().isOk())
//期望返回的结果集合有两个元素
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2))
//添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台
.andDo(MockMvcResultHandlers.print());
}
5 测试Post请求
@Test
void insert() throws Exception {
User user = new User();
user.setNickname("yunqing");
String jsonResult = JSONObject.toJSONString(user);
//直接自定义save返回true
when(userService.save(any())).thenReturn(true);
// perform : 执行请求 ;
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders
//MockMvcRequestBuilders.post("/url") : 构造一个post请求
.post("/user/insert")
.accept(MediaType.APPLICATION_JSON)
//传参,因为后端是@RequestBody所以这里直接传json字符串
.content(jsonResult)
// 请求type : json
.contentType(MediaType.APPLICATION_JSON))
// 期望的结果状态 200
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();//返回结果
int statusCode = mvcResult.getResponse().getStatus();
String result = mvcResult.getResponse().getContentAsString();
//单个断言
Assertions.assertEquals(200, statusCode);
//多个断言,即使出错也会检查所有断言
assertAll("断言",
() -> assertEquals(200, statusCode),
() -> assertTrue("true".equals(result))
);
常用API
//使用jsonPaht验证返回的json中code、message字段的返回值
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value("00000"))
.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("成功"))
//body属性不为空
.andExpect(MockMvcResultMatchers.jsonPath("$.body").isNotEmpty())
// 期望的返回结果集合有2个元素 , $: 返回结果
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2));
import cn.johnny.bd.dataservice.biz.cansignal.service.SignalNamesMappingCacheService;
import cn.johnny.bd.dataservice.biz.dataservice.mapper.IQueryJobMapper;
import cn.johnny.bd.dataservice.common.debug.Print;
import cn.johnny.bd.dataservice.common.sqlTemplate.GlobalInlineVariableNamesEnum;
import cn.johnny.bd.dataservice.model.entity.SignalFieldMapping;
import com.google.common.cache.CacheStats;
import com.google.common.cache.LoadingCache;
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.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.AopTestUtils;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.Mockito.*;
//@ExtendWith(MockitoExtension.class)
// MockitoJUnitRunner 为开发者提供了 Mockito 框架使用情况的自动验证,以及自动执行 initMocks()
@RunWith(MockitoJUnitRunner.class) // SpringJUnit4ClassRunner / SpringRunner / MockitoJUnitRunner
public class MockitoTest {
private static final Logger logger = LoggerFactory.getLogger(MockitoTest.class);
// @Mock
// private String canParseMatrixConfigDBName; // [X] 无法 Mock final class
/**
* 使用 @Mock 注解封装需要被模拟调用的对象 | @Mock: 创建一个Mock.
*/
@Mock
private IQueryJobMapper queryJobMapper;
@Mock
private LoadingCache<String, Map<String, SignalFieldMapping>> signalNamesMappingCache;
/**
* 使用 @InjetcMock 注解是为了向里面添加 @Mock 注入的对象 | @InjectMocks: 创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。
*/
@InjectMocks
private SignalNamesMappingCacheService cacheService;
@Before
public void setup(){
ReflectionTestUtils.setField(cacheService, "canParseMatrixConfigDBName", "johnny_bdp");//final Class(String) 无法成为 Mock 对象。故通过这种 Spring 提供的 ReflectionTestUtils 工具注入该属性
// ReflectionTestUtils.setField(cacheService, "queryJobMapper", queryJobMapper);
// ReflectionTestUtils.setField(cacheService, "signalNamesMappingCache", signalNamesMappingCache);
}
/**
* @description
* // step1 ready dataset for test stubs(准备测试桩所需的基础数据集)
* // step2 setup test stubs(设置测试桩)
* // step3 Run the target test class and method (执行测试目标类的目标方法)
* // step4 assert , verify and end over(断言、验证与结束)
*/
@Test
public void getSignalNamesMappingTestSuccess(){
// step1 ready dataset for test stubs(准备测试桩所需的基础数据集)
List<SignalFieldMapping> signalList = new ArrayList<>();
SignalFieldMapping signalFieldMapping1 = new SignalFieldMapping(1, "bcm_pepsPowerMode", "bcm_peps_power_mode", "bcm_pepsPowerMode", "{\"0\":\"DEFAULT_POWERMODE\",\"1\":\"OFF_POWERMODE\",\"2\":\"ON_POWERMODE\",\"3\":\"RESERVE_POWERMODE\",\"4\":\"RESERVE_POWERMODE1\",\"5\":\"RESERVE_POWERMODE2\",\"6\":\"RESERVE_POWERMODE3\",\"7\":\" INVALID_POWERMODE\"}");
SignalFieldMapping signalFieldMapping2 = new SignalFieldMapping(2, "bcm_pepsKeyNotInCarInd", "bcm_peps_key_not_in_car_ind", "Keyisnotincarindication.钥匙离开车内提示.", "{\"0\":\"NO_WARNING\",\"1\":\" WARNING\"}");
signalList.add(signalFieldMapping1);
signalList.add(signalFieldMapping2);
CacheStats cacheStats = new CacheStats(1,1,1,1,1,1);
String globalInlineVariableNamesCode = GlobalInlineVariableNamesEnum.SIGNAL_NAMES_ORIGIN_MAPPING.getCode();
// step2 setup test stubs(设置测试桩)
when(queryJobMapper.getSignalFieldMapping("johnny_bdp")).thenReturn(signalList);
when(signalNamesMappingCache.stats()).thenReturn(cacheStats);
// step3 Run the target test class and method (执行测试目标类的目标方法)
cacheService.init();
Map<String, SignalFieldMapping> signalFieldMappingMap = cacheService.getSignalNamesMapping(globalInlineVariableNamesCode);
// step4 assert , verify and end over(断言、验证与结束)
if(!signalFieldMappingMap.isEmpty()){
logger.debug("signalFieldMappingMap is not empty, content as follows:");
Print.print(signalFieldMappingMap);
}
Assert.assertNotNull(signalFieldMappingMap);
}
/**
* 基本模拟测试1
* @reference-doc
* [1] 走进Java接口测试之Mock(概念篇) - Tencent Cloud - https://cloud.tencent.com/developer/article/1465589
*/
@Test
public void mockitoBaseTest(){
// 创建Mock对象,参数可以是类或者接口
List<String> list = mock(List.class);
// 设置方法的预期返回值
when(list.get(0)).thenReturn("zuozewei");
when(list.get(1)).thenThrow(new RuntimeException("test exception"));
String result = list.get(0);
logger.warn("result:{}", result);// zuozewei
// 验证方法调用, 若有异常时会直接抛 Exception
String verifyResult = verify(list).get(0);
logger.warn("verifyResult:{}", verifyResult);//null
//断言,list的第一个元素是否是 "zuozwei"
Assert.assertEquals(result,"zuozewei");
}
/**
* 基本模拟测试2
*/
@Test
public void mockBaseTest2(){
//一旦mock对象被创建了,mock对象会记住所有的交互。然后你就可以选择性的验证感兴趣的交互
//You can mock concrete classes, not only interfaces
// 你可以mock具体的类型,不仅只是接口
//创建 mock 对象,mock 1个 List 接口
// List mockedList = mock(List.class);
//若不使用静态导入,则:必须使用 Mockito 调用
// List mockedList = Mockito.mock(List.class);
LinkedList mockedList = mock(LinkedList.class);
//stubbing
// 测试桩
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());
//following prints "first"
// 输出 “first”
System.out.println(mockedList.get(0));
//following prints "null" because get(999) was not stubbed
// 因为get(999) 没有打桩,因此输出null
System.out.println(mockedList.get(999));
//Although it is possible to verify a stubbed invocation, usually it's just redundant
//If your code cares what get(0) returns then something else breaks (often before even verify() gets executed).
//If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See here.
// 验证 get(0) 被调用的次数
verify(mockedList).get(0);
// following throws runtime exception
// 抛出异常 | 因 get(1) 的测试桩是抛出异常
// System.out.println(mockedList.get(1));
}
/**
* 基本模拟测试3
*/
@Test
public void mockBaseTest3(){
// 生成 mock 对象
Foo mockFoo = mock(Foo.class);
// 测试桩
when(mockFoo.bool(anyString(), anyInt(), any(Object.class))).thenReturn(true);
// 验证/断言
Assert.assertTrue(mockFoo.bool("A", 1, "A"));
Assert.assertTrue(mockFoo.bool("B", 10, new Object()));
// 测试桩
when(mockFoo.bool(eq("false"), anyInt(), any(Object.class))).thenReturn(false);
// 验证/断言
Assert.assertFalse(mockFoo.bool("false", 10, new Object()));
}
}
class Foo {
boolean bool(String str, int i, Object obj) {
return false;
}
int in(boolean b, List<String> strs) {
return 0;
}
int bar(byte[] bytes, String[] s, int i) {
return 0;
}
}
<!-- org.junit.runner.RunWith;org.junit.Assert;org.junit.Before;org.junit.Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- 4.13.1 -->
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- org.slf4j.Logger ; org.slf4j.LoggerFactory; -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<!-- 1.7.25 -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<!-- 1.7.25 -->
</dependency>
<!--
org.mockito.Mockito; org.mockito.MockedStatic;
org.mockito.junit.MockitoJUnitRunner;
org.mockito.InjectMocks; org.mockito.Mock;
org.mockito.ArgumentMatchers.any; org.mockito.ArgumentMatchers.eq
-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<!-- 3.4.0 -->
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<!-- 3.4.0 -->
<version>${mockito.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<!-- 3.4.0 -->
<version>${mockito.version}</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>mockito-core</artifactId>
<groupId>org.mockito</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.jsonzou</groupId>
<artifactId>jmockdata</artifactId>
<!-- 4.3.0 -->
<version>${jmockdata.version}</version>
<scope>test</scope>
</dependency>
import cn.johnny.bd.dataservice.TestApplication;
import cn.johnny.bd.dataservice.biz.cansignal.service.SignalNamesMappingCacheService;
import cn.johnny.bd.dataservice.biz.dataservice.mapper.IQueryJobMapper;
import cn.johnny.bd.dataservice.common.debug.Print;
import cn.johnny.bd.dataservice.common.sqlTemplate.GlobalInlineVariableNamesEnum;
import cn.johnny.bd.dataservice.model.entity.SignalFieldMapping;
//import com.github.jsonzou.jmockdata.MockConfig;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class SpringJUnitTest {
private static final Logger logger = LoggerFactory
.getLogger(SpringJUnitTest.class);
@Resource
private IQueryJobMapper queryJobMapper;
@Resource
private SignalNamesMappingCacheService cacheService;
@Before
public void init() {
}
@Test
public void test(){
String globalInlineVariableNamesCode = GlobalInlineVariableNamesEnum.SIGNAL_NAMES_ORIGIN_MAPPING.getCode();
Map<String, SignalFieldMapping> signalFieldMappingMap = cacheService.getSignalNamesMapping(globalInlineVariableNamesCode);
Print.print(signalFieldMappingMap);
Assert.assertNotNull(signalFieldMappingMap);
}
}
////////////// TestApplication //////////////
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({"cn.johnny"})
public class TestApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(TestApplication.class).web(WebApplicationType.NONE).run(args);
}
}
<!-- org.junit.runner.RunWith;org.junit.Assert;org.junit.Before;org.junit.Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- 4.13.1 -->
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- org.slf4j.Logger ; org.slf4j.LoggerFactory; -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<!-- 1.7.25 -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<!-- 1.7.25 -->
</dependency>
<!-- org.springframework.boot.test.context.SpringBootTest -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.3.12.RELEASE</version>
<!-- <scope>compile</scope> -->
</dependency>
<!-- org.springframework.test.context.junit4.SpringJUnit4ClassRunner; org.springframework.test.util.ReflectionTestUtils; -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<!-- 5.2.15.RELEASE -->
<scope>test</scope>
</dependency>
Mockito是mocking框架,它让你用简洁的API做测试。而且Mockito简单易学,它可读性强和验证语法简洁。
Mockito是GitHub上使用最广泛的Mock框架,并与JUnit结合使用。
Mockito框架可以创建和配置mock对象。
使用Mockito简化了具有外部依赖的类的测试开发。
常用的mock框架有:EasyMock、JMock、Mockito、PowerMockito。比较常用的是Mockito。
比较项
EasyMock
JMock
Mockito
PowerMockito
final方法
不支持
不支持
不支持
支持
private方法
不支持
不支持
不支持
支持
静态方法
不支持
不支持
支持
支持
SpringBoot依赖
实现较为复杂
实现较为复杂
默认依赖
基于Mockito扩展
API风格
略复杂
略复杂
简单
简单
手机扫一扫
移动阅读更方便
你可能感兴趣的文章