Mockito InjectMocks字段无法注入其他InjectMocks字段的解决办法

您所在的位置:网站首页 mock注解不生效 Mockito InjectMocks字段无法注入其他InjectMocks字段的解决办法

Mockito InjectMocks字段无法注入其他InjectMocks字段的解决办法

2023-08-31 10:15| 来源: 网络整理| 查看: 265

今天写单元测试用例,跑起来后,出现了空指针异常。于是查了下,发现Mock对象的一个属性未注入,为null。我的程序结构大致为:

@Repository public class MyRepository { public void doSomething() { System.out.println("here's dosomething"); } public Model findById(Long id) { return new Model(id, "Real Repository"); } } @Service public class MyService { @Autowired private MyRepository myRepository; public void doSomething() { this.myRepository.doSomething(); } public Model findById(Long id) { return this.myRepository.findById(id); } } @Controller public class MyController { @Autowired private MyService myService; public void doSomething() { this.myService.doSomething(); } public Model findById(Long id) { return this.myService.findById(id); } } @RunWith(MockitoJUnitRunner.class) public class MyControllerTest { @Mock private MyRepository myRepository; @InjectMocks private MyService myService; @InjectMocks private MyController myController; @Before public void setUp() throws Exception { Model model = new Model(11L, "AAA"); doNothing().when(myRepository).doSomething(); when(myRepository.findById(11L)).thenReturn(model); } @Test public void doSomething() throws Exception { this.myController.doSomething(); } @Test public void findById() throws Exception { System.out.println(this.myController.findById(11L)); } } 使用Mock打桩的为MyRepository,原本以为使用InjectMocks后,MyService会自动注入MyRepository,MyController会自动注入前的MyService,但是结果并不是这样的。MyController认不到MyService。MyController实例后,没有给myService属性赋值。看起来InjectMocks只能使用Mock注解的。于是想在 MyService上加个Mock,虽然编译没问题,但是运行起来异常了:

org.mockito.exceptions.base.MockitoException: This combination of annotations is not permitted on a single field: @Mock and @InjectMocks于是只能另寻他路,考虑到使用Spring来做容器管理,修改Test类:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:beans.xml"}) public class MyControllerTest { @Mock private MyRepository myRepository; @InjectMocks @Autowired private MyService myService; @Autowired private MyController myController; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); Model model = new Model(11L, "AAA"); doNothing().when(myRepository).doSomething(); when(myRepository.findById(11L)).thenReturn(model); } @Test public void doSomething() throws Exception { this.myController.doSomething(); } @Test public void findById() throws Exception { System.out.println(this.myController.findById(11L)); } }果然可以了,模拟了数据库访问:

@autowire加哪里还有讲究,必须2个都加,否则也会出现注入不到的情况。

既然没法注入,其实不借助容器,也可以手动来赋值。在setup方法中做下修改,便得到方法二:

@RunWith(MockitoJUnitRunner.class) public class MyControllerTest { @Mock private MyRepository myRepository; @InjectMocks private MyService myService; @InjectMocks private MyController myController; @Before public void setUp() throws Exception { ReflectionTestUtils.setField(myController, "myService", myService); Model model = new Model(11L, "AAA"); doNothing().when(myRepository).doSomething(); when(myRepository.findById(11L)).thenReturn(model); } @Test public void doSomething() throws Exception { this.myController.doSomething(); } @Test public void findById() throws Exception { System.out.println(this.myController.findById(11L)); } } 执行效果是一样的,如上图。

两种方法都能满足多级的注入情形。如果不想依赖Spring,可以选择用第2种的方式。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3