mybatis-plus作为mybatis的增强工具,在使用过程中简化开发,大大得提高了工作效率。mybatis-plus提供了一套通用的mapper和service *** 作,对于单表 *** 作很方便,但是在写单元测试的时候还是存在有很多不同于mybatis的地方。本文介绍本人在开发过程当中遇到的一些坑和自己的理解。
Mock是在测试过程中,对于一些不容易构造的对象,创建一个mock对象来模拟对象的行为。比如说当写单元测试不想调用数据库时,就可以在调用mapper的方法时使用Mock打桩,mock想要返回的结果。
依赖引用Servicecom.baomidou mybatis-plus-boot-starter3.3.1 org.mockito mockito-core2.23.4 test org.powermock powermock-api-mockito22.0.2 test org.powermock powermock-module-junit42.0.2 test org.powermock powermock-core2.0.2 test org.powermock powermock-module-junit4-rule2.0.2 test junit junit4.12 test
@Service public class TestServiceImpl extends ServiceImpl单元测试implements TestService { @Override public boolean insert(UserInfo userInfo) { return this.save(userInfo); } @Override public boolean insertList(List list) { return this.saveBatch(list, 1000); } }
首先对单个插入进行单元测试,通过分析mybatis-plus自带的ServiceImpl,发现save方法调用的Mapper的insert方法
default boolean save(T entity) { return SqlHelper.retBool(this.getbaseMapper().insert(entity)); }
单元测试代码如下:
@RunWith(PowerMockRunner.class) @SpringBootTest public class TestServiceImplTest { @InjectMocks private TestServiceImpl testService; @Mock private TestMapper testMapper; @Test public void testInsert() { UserInfo userInfo = new UserInfo(); userInfo.setId(1); userInfo.setName("张三"); //对mapper的insert打桩,返回成功标识1 PowerMockito.when(testMapper.insert(userInfo)).thenReturn(1); Assert.assertTrue(testService.insert(userInfo)); } }
单个插入的单元测试就很简单,但是通过分析批量插入的saveBatch方法发现没有通过Mapper,而是直接在service层实现的,这时该在哪个方法上打桩?有没有办法直接在saveBatch方法上打桩?
public boolean saveBatch(CollectionentityList, int batchSize) { String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE); return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> { sqlSession.insert(sqlStatement, entity); }); }
protectedboolean executeBatch(Collection list, int batchSize, BiConsumer consumer) { Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]); return !CollectionUtils.isEmpty(list) && this.executeBatch((sqlSession) -> { int size = list.size(); int i = 1; for(Iterator var6 = list.iterator(); var6.hasNext(); ++i) { E element = var6.next(); consumer.accept(sqlSession, element); if (i % batchSize == 0 || i == size) { sqlSession.flushStatements(); } } }); }
首先,尝试直接在Mock对象TestServiceImpl的saveBatch方法上打桩,结果直接报错,无法运行
@Test public void testInsertList() { PowerMockito.when(testService.saveBatch(Mockito.anyList())).thenReturn(true); Listlist = new ArrayList<>(); UserInfo userInfo = new UserInfo(); userInfo.setId(1); userInfo.setName("张三"); list.add(userInfo); Assert.assertTrue(testService.insertList(list)); }
Mockito.spy()可以在真实对象上创建间谍(类似于浅克隆),尝试在创建的间谍对象上打桩
@Test public void testInsertList() { //创建spy间谍对象 TestService spy = Mockito.spy(testService); PowerMockito.doReturn(true).when(spy).saveBatch(Mockito.anyList()); Listlist = new ArrayList<>(); UserInfo userInfo = new UserInfo(); userInfo.setId(1); userInfo.setName("张三"); list.add(userInfo); //特别注意,spy对象和testService对象是两个不同的对象,一定要调用spy对象的insertList方法 Assert.assertTrue(spy.insertList(list)); }
测试结果通过,完美解决Mybatis-plus批量插入的单元测试
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)