• @Mock @MockBean @InjectMocks之间的关系


    首先说@mock 和 @MockBean
    具体的介绍大家可以看
    Mockito的@Mock与@MockBean

    一言以蔽之就是
    @Mock可以生产一个空的类,这个类的方法体都是空的,方法的返回值(如果有的话)都是null。
    @MockBean可以生产一个空的类,并且用这个类替代spring容器中同类型的类。

    而@InjectMocks就是产生一个空的类,这个类里面的字段用这个测试类里面被@Mock的字段填充。

    @SpringBootTest
    public class MockitoTest {
    
        @MockBean
        private MyService myService;
    
        @InjectMocks
        private  UserController userController;
     @Test
        public void testGet(){
    
    
            Person person = new Person();
            person.setName("张三");
            Long id = 15L;
            when(personMapper.selectById(id)).thenReturn(person);
            when(myService.say()).thenReturn("by mock");
            Person result = userController.getUserById(id);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    我写了上面的测试代码,发现不论怎么运行,userController里面的MyService 字段都是null,感觉就是userController里面MyService 字段上面的autowired没有起作用。
    我一直在调整代码,发现了如下的情况

    • 前提条件
      ClassB里面有个ClassA,classa被标注了Autowired

    • case1
      测试类上只有 @ExtendWith(MockitoExtension.class) 的情况下 测试类里被 @MockBean 标注的字段就是空的

    • case2
      测试类上只有 @ExtendWith(SpringExtension.class)的情况下
      测试类里被 @MockBean 标注的字段(假定为ClassA)不是空的
      但是被 @InjectMocks标注的类(假定为ClassB)
      ClassB里面标注了Autowired的ClassA依然是null

    • case3
      @SpringBootTest 里面本身就包含着 @ExtendWith(SpringExtension.class)
      如果测试类上只有 @SpringBootTest 测试类里被 @MockBean 标注的字段(假定为ClassA)不是空的
      但是被 @InjectMocks标注的类(假定为ClassB)
      ClassB里面标注了Autowired的ClassA依然是null

    • case4
      如果测试类上只有 @ExtendWith(MockitoExtension.class)
      测试类里被 @Mock标注的字段不是null,也能正常的注入被 @InjectMocks标注的类

    • case5
      如果测试类上只有 @SpringBootTest
      虽然测试类里classB被标注了 @InjectMocks
      但是classB里面的classA依然是null 即使代码里面的ClassA类上标注了 @Component

    看到我头都大了。
    我的目标就是把 @MockBean标注的类注入到@InjectMocks里面。但是一直不行。

    最终我把@InjectMocks改成了@autowired 发现可以注入了
    但是被标注了@autowired里面缺不能注入被标注了@mock的字段!

    最终得到一个结论
    被@InjectMocks标注的字段,只能被注入被@mock标注的类(@mockbean标注的不行)
    被@autowired标注的字段,只能被注入被@mockbean标注的类(@mock标注的不行)

    再简而言之就是
    要想把需要打桩的类注入到我们要测试的类里面,有下面两个思路

    • @ExtendWith(MockitoExtension.class) + @InjectMocks +@Mock
    • @SpringBootTest +@Autowired+@MockBean
      两个的区别在于
      • 是否启动了SpringBoot。(当然这个区别没有现实意义,因为我写代码做测试的目的是验证模块功能的正确性,是否启动Spirngboot只是手段不是目的)
      • 启动SpringBoot方便做集成测试,使用ExtendWith(MockitoExtension.class)方便做模块内简单的单元测试。(至于这两种测试的区别,google上的说明有很多,不过我同时的认为前者测试的范围更广,粒度也更大,依赖的模块更多,依赖也要求是真实实现的)

    参考资料

  • 相关阅读:
    Python趣味操作推荐
    Spring Kafka生产者实现
    RedisJson 横空出世!
    取产品之道、赚效率的钱,锅圈万店背后的赢家法则
    CS-NP白蛋白包覆壳聚糖纳米颗粒/人血清白蛋白-磷酸钙纳米颗粒无机复合材料
    爬虫逆向实战(30)-某查查股东关联公司(HmacSHA512)
    jQuery、vue、小程序、uni-app中的本地存储数据和接受数据是什么?
    多通道ECG心率监测系统
    无向图欧拉路径问题
    Mental Poker- Part 2
  • 原文地址:https://blog.csdn.net/dlf123321/article/details/127940122