前言
package com.netease.kaola.mock.test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.netease.kaola.mock.test.bean.Father;
import com.netease.kaola.mock.test.bean.Grandson;
/**
* Created by chenghan on 17/9/18.
*/
public class TypeMockMokitoTest {
private static final String MOCK_NAME = "mock grandson";
/**
* mockito原生注解,表明待做mock分析的入口类,分析后满足条件的字段会被替换为mock后的实现
*/
@InjectMocks
private Father father = new Father();
/**
* 按照类型做mock,会替换入口类所有类型匹配的字段(包括嵌套类的字段),返回值默认都是null
*/
@Mock
private Grandson grandson;
@BeforeClass
public void beforeClass() {
MockitoAnnotations.initMocks(this);
}
@AfterClass
public void afterClass() {
}
@Test
public void mokito类型匹配mock() {
String mokitoReturn = "mokito";
Mockito.when(grandson.name()).thenReturn(mokitoReturn);
String result = father.getGrandsonOfFather().name();
Assert.assertTrue(result.equals(mokitoReturn));
result = father.getSon().getGrandson().name();
Assert.assertTrue(result.equals(mokitoReturn));
}
}
mockito可以支持注解方式,按照类型进行注解对象替换,如果我们要替换的对象都很规矩的话,那么到此mockito已经可以基本解决我们的mock需求了。但是,我们想要mock的对象一般都是dubbo 接口,dubbo接口的类型可就不那么“规矩”了,会被代理为形如
com.alibaba.dubbo.common.bytecode.proxyXX”的类型,那么mockito的类型替换就失效了。此外,mockito不支持按照字段名替换,也没办法一键恢复到mock之前的状态。
按照字段名替换 | 按照字段类型替换 | 恢复mock前初始状态 | |
---|---|---|---|
mockito | 不支持 | 支持简单类型替换 | 不支持 |
haitao-mock | 支持 | 支持简单类型替换,并且可以识别被代理后的类,比如dubbo service | 支持 |
<dependency>
<groupId>com.netease.haitao</groupId>
<artifactId>haitao-mock</artifactId>
<version>1.0.6</version>
<scope>test</scope>
</dependency>
初始化
/**
* 测试抽象类 Created by chenghan on 17/7/3.
*/
public abstract class AbstractTestClass {
@BeforeClass
public void beforeClass() {
// 初始化mock框架
MockController.mockStart(this);
}
@AfterClass
public void afterClass() {
// 用例执行完,清理并回复到mock之前的场景
MockController.mockClear(this);
}
}
按照字段名替换
/**
* Created by chenghan on 17/7/4.
*/
public class NameMockTest extends AbstractTestClass {
private static final String MOCK_NAME = "mock grandson";
/**
* mockito原生注解,表明待做mock分析的入口类,分析后满足条件的字段会被替换为mock后的实现
*/
@InjectMocks
private Father father = new Father();
/**
* 按照字段名做mock
*/
@NameMock(mockFieldName = "grandsonOfFather")
private Grandson grandson = EasyMockBoostUtils.buildMock(new EasyMockBoostUtils.MockTemplate() {
public Grandson buildMock() {
Grandson mockGrandSon = EasyMock.createMock(Grandson.class);
EasyMock.expect(mockGrandSon.name()).andReturn(MOCK_NAME).anyTimes();
EasyMock.replay(mockGrandSon);
return mockGrandSon;
}
});
@Test
public void 字段名mock() {
String result = father.getGrandsonOfFather().name();
Assert.assertTrue(result.equals(MOCK_NAME));
result = father.getSon().getGrandson().name();
Assert.assertTrue(!result.equals(MOCK_NAME));
}
}
按照字段类型替换
/**
* Created by chenghan on 17/7/4.
*/
public class TypeNestMockTest {
private static final String MOCK_NAME = "mock grandson";
/**
* mockito原生注解,表明待做mock分析的入口类,分析后满足条件的字段会被替换为mock后的实现
*/
@InjectMocks
private Father father = new Father();
/**
* 按照类型做mock,会替换入口类所有类型匹配的字段(包括嵌套类的字段)
*/
@TypeMock
private Grandson grandson = EasyMockBoostUtils.buildMock(new EasyMockBoostUtils.MockTemplate() {
public Grandson buildMock() {
Grandson mockGrandSon = new Grandson();
Mockito.when(mockGrandSon.name()).thenReturn(MOCK_NAME);
return mockGrandSon;
}
});
@BeforeClass
public void beforeClass() {
MockController.mockStart(this);
}
@AfterClass
public void afterClass() {
MockController.mockClear(this);
}
@Test
public void haitaoMock类型匹配mock() {
String result = father.getGrandsonOfFather().name();
Assert.assertTrue(result.equals(MOCK_NAME));
result = father.getSon().getGrandson().name();
Assert.assertTrue(result.equals(MOCK_NAME));
}
}
本文来自网易实践者社区,经作者程汉授权发布。