首先说@mock 和 @MockBean
具体的介绍大家可以看
https://blog.csdn.net/dlf123321/article/details/127931154?spm=1001.2014.3001.5501
一言以蔽之就是
@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);
}
我写了上面的测试代码,发现不论怎么运行,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标注的不行)