Mockito InjectMocks字段无法注入其他InjectMocks字段的解决办法
2017-06-17 01:16
309 查看
今天写单元测试用例,跑起来后,出现了空指针异常。于是查了下,发现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");
}
}
使用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种的方式。
@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种的方式。
相关文章推荐
- mybatis下无法通过service注入查询到mysql的text的字段信息的解决办法
- Spring Cloud/Boot WebSocket 无法注入其他类的解决办法
- win2003下bcb6kg.EXE无法运行以及其他某些程序运行出错的解决办法
- 局域网中无法访问其他电脑的解决办法
- IE6-IE9兼容性问题列表及解决办法_补充之五:在IE9下, disabled的文本框内容被选中后,其他控件无法获得焦点问题
- 【水晶玻璃鞋 11】解决Filezilla server 搭建的FTP服务器本机可以访问,而其他主机无法访问的办法(不关防火墙)
- SQLite无法使用drop column删除表字段解决办法
- win7下架设IIS其他电脑无法访问的解决办法
- 【ZT】网站字符型字段被注入的解决办法
- SQL字段为null返回0或其他解决办法
- Ubuntu 无法调节亮度解决办法 for Acer笔记本(其他的笔记本也可以试试)
- "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法
- "无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开"解决办法
- 某一个字段去重,其他字段全部查询的解决办法
- [转]lenovo.com.cn 及其他联想旗下网站无法访问的解决办法
- 用VS2010编写的C++程序,在其他电脑上无法运行,提示缺少mfc100.dll的解决办法
- PDO取Oracle lob大字段,当数据量太大无法取出的问题的解决办法
- ora-12154 tns 无法处理服务名(执行的程序途径不一致导致,枚举网络数种方法,大家还有其他解决办法?)
- Android SDK Manager在添加Platforms和其他Packages时提示无法在相应目录创建文件夹的解决办法!
- SQLite无法使用drop column删除表字段解决办法