baomidou / mybatis-plus

An powerful enhanced toolkit of MyBatis for simplify development
https://baomidou.com
Apache License 2.0
16.36k stars 4.31k forks source link

单元测试中无法mock mapper方法返回我预定返回的值 #4754

Closed HeCHieh closed 1 year ago

HeCHieh commented 2 years ago

当前使用版本(必填,否则不予处理)

com.baomidou mybatis-plus-boot-starter 3.5.1

该问题是如何引起的?(确定最新版也有问题再提!!!)

测试代码

package com.example.mybatisplusmockdemo;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@SpringBootTest(classes = MybatisplusMockDemoApplication.class)
public class HomePopUpConfigServiceTest {
    @Autowired
    private HomePopUpConfigService homePopUpConfigService;
    @MockBean
    private HomePopUpConfigMapper homePopUpConfigMapper;

    @Test
    public void testPageList() {
        PageDTO pageDTO = new PageDTO();
        pageDTO.setLimit(10L);
        pageDTO.setCurrent(1L);

        Page<HomePopUpConfig> page = Page.of(pageDTO.getCurrent(), pageDTO.getLimit());
        HomePopUpConfig build = HomePopUpConfig.builder().build();
        page.setRecords(List.of(build));
        page.setTotal(1L);
        page.setPages(1L);
        page.setSize(10L);
        page.setPages(1L);

        given(this.homePopUpConfigMapper.selectPage(page, null)).willReturn(page);

        Page<HomePopUpConfig> pages = this.homePopUpConfigService.list(pageDTO);

        assertEquals(1L, pages.getPages());
        assertEquals(1L, pages.getTotal());
        assertEquals(10L, pages.getSize());
        assertEquals(1L, pages.getPages());
        List<HomePopUpConfig> data = pages.getRecords();
        assertFalse(data.isEmpty());

        verify(homePopUpConfigMapper, times(1))
                .selectPage(page, null);
    }
}

下面代码没按预期mock值返回

package com.example.mybatisplusmockdemo;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
@RequiredArgsConstructor
public class HomePopUpConfigServiceImpl implements HomePopUpConfigService {
    private final HomePopUpConfigMapper homePopUpConfigMapper;

    @Override
    public Page<HomePopUpConfig> list(PageDTO pageDTO) {
        Page<HomePopUpConfig> page = Page.of(pageDTO.getCurrent(), pageDTO.getLimit());
        //运行上面测试代码,这里的homePopUpConfigPage对象不是我mock返回的对象值, 返回了null
        Page<HomePopUpConfig> homePopUpConfigPage = this.homePopUpConfigMapper.selectPage(page, null);
        return homePopUpConfigPage;
    }
}

复现代码示例

报错信息

无报错信息

Seayon commented 1 year ago

在你的 given 方法中,定义了入参 page,当 selectPage 传入此参数时返回预先定义的 page 值

given(this.homePopUpConfigMapper.selectPage(page, null)).willReturn(page);

但在实际调用中,com.example.mybatisplusmockdemo.HomePopUpConfigServiceImpl#list 方法中,使用入参自行产生了新的 Page 对象,这两个 Page 对象不是同一个,所以无法匹配和捕获

Page<HomePopUpConfig> page = Page.of(pageDTO.getCurrent(), pageDTO.getLimit());

我通常这么使用,使用

given(this.homePopUpConfigMapper.selectPage(ArgumentMatchers.any(Page.class), ArgumentMatchers.isNull())).willReturn(page);

这是一种比较粗犷的使用方式,如果要精确匹配,可能需要自定义匹配方式,如下

given(this.homePopUpConfigMapper.selectPage(ArgumentMatchers.argThat(homePopUpConfigIPage -> homePopUpConfigIPage.getSize() ==10L && homePopUpConfigIPage.getCurrent() == 1L), ArgumentMatchers.isNull())).willReturn(page);

另外,这个应该是 mockito 的使用问题,感觉提到那边更合适。

miemieYaho commented 1 year ago

如上,走路摔了不要直接怪地不平