1.mock泛型方法
- 反射获取Method时,泛型类型使用 Object.class 替换。
- 调用方法时,泛型入参,不能使用new Object(), 需要使用具体的实现类。
1.1 源代码
public abstract class Test<OUT> {
private void setOutPut(OUT model, Map<String, String> params) {
// do something
}
}
public class TestSub extends Test<TestSubDO>{
// do something
}
1.2 mock代码
@RunWith(MockitoJUnitRunner.class)
public class TestTest {
@InjectMock
private Test test = new TestSub();
@Test
public void test1(){
// OUT 使用 Object.class 替换
Method method = Test.class.getDeclaredMethod("setOutPut", Object.class, Map.class);
method.setAccessible(true);
// TestSubDO
method.invoke(test, new TestSubDO(), new HashMap());
}
}
2.循环中多次调用同一方法
在一个循环中多次调用同一个有返回值的方法,模拟多次返回值,需要多次使用thenReturn方法,或在thenReturn中设置多个值。
2.1源代码
while(true){
Page<TestPO> pageList = testMapper.selectPage(pageQuery);
if(CollectionUtils.isEmpty(pageList.getData())) {
break;
}
// todo something
}
2.2 mock代码
Page<TestPO> page1=new Page(1,10,1,Lists.newArrayList(new TestPO()));
Page<TestPO> page2=new Page(1,10,1,Collections.emptyList());
// 第二次调用返回数据为空,则会退出while循环
when(testMapper.selectPage(any())).thenReturn(page1).thenReturn(page2);
3.MockitoException for Static Mocks异常
在test/resources文件夹下追加:
- 新建文件夹 mockito-extensions
- 在新的文件夹中新建文本文件 org.mockito.plugins.MockMaker
- 向文本中写入内容:mock-maker-inline
4.模拟protected方法
有2种方式可以模拟protected方法。
4.1方式1使用ReflectionSupport
ReflectionSupport类是JUnit5提供的一个类。可以使用 invokeMethod方法,执行protected方法。
public static Object
invokeMethod(Method method, Object target, Object ...args)
4.2方式2使用Answers.CALLS_REAL_METHODS
注意:这种方式时,需要将xxxTest.java的package路径和xxx.java类的package路径保持一致,不一致时调用protected方法时报错。
Abstarct ab = mock(Abstarct.class, Answers.CALLS_REAL_METHODS);
ab.protectedMethod();
5.mybatis-plus相关问题
5.1 MyBatisPlusException:can not find lambda cache for this entity
解决方法是在单测方法第一行加入一行代码:
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), "")
, TestPO.class);
注意:TestPO是数据库表对应的实体类。
6.模拟EasyExcel读取数据
6.1源代码
读取Excel文件时使用以下方法:
EasyExcel.read(String filePath, Class head, ReadListener listener);
源代码应用:
@Data
public class TestDO {
@ExcelProperty(value = "名称", index = 0)
private String name;
}
public class ReadTestListener extend AnalysisEventListener<TestDO> {
private List<TestDO> dataList = new ArrayList<>();
public List<TestDO> getDataList() {
return this.dataList;
}
// 覆写方法 invoke, doAfterAllAnalysed
}
// 后面要mock的方法
public void readExcel(String filePath) {
ReadTestListener listener = new ReadTestListener();
EasyExcel.read(filePath, TestDO.class, listener).sheet().doRead();
}
6.2 mock代码
@Test
public void test1() {
String filepath = "c:\\testdata\testDo.xlsx";
ExcelReaderBuilder readerBuilder = Mockito.mock(ExcelReaderBuilder.class);
try(MockedStatic mockEasyExcel = Mockito.mockStatic(EasyExcelFactory.class, invocation -> {
if (invocation.getMethod().getName().equals("read")) {
return readerBuilder;
}
return null;
})) {
ExcelReaderSheetBuilder excelReaderSheetBuilder=mock(ExcelReaderSheetBuilder.class);
when(readerBuilder.sheet()).thenReturn(excelReaderSheetBuilder);
doNothing().when(excelReaderSheetBuilder).doRead();
// 调用mock的方法
readExcel(filepath);
}
}
后续遇到问题会继续补充。