在我的实现类中,我有一个读写锁定义,如下所示,
@Inject
@Named("CustomizedLock")
private ReentrantReadWriteLock rwLock;
我在名为run()
的方法中使用它,
rwLock.writeLock().lock();
锁定进程。但是,当我尝试使用mockito测试时,我发现ReentrantReadWriteLock
已初始化。但是当我试图获得rwLock.writeLock()
时,它是空的。这是我的考试。
@Mock
private ReentrantReadWriteLock feedReadWriteLock;
@InjectMocks
private CustomModule module = mock(CustomModule.class);
/////////////////////////
@Test
public void test() {
when(module.getReadWriteLock()).thenReturn(mock(ReentrantReadWriteLock.class));
PowerMockito.doReturn(new ReentrantReadWriteLock()).when(module.getReadWriteLock());
cacheJob.run();
}
正如我所说rwLock.writeLock()
为空但rwLock已初始化。请解释一下mockito如何发生这种情况。这样做的理想方法是什么?
答案 0 :(得分:2)
你正在嘲笑错误:
@Mock
private ReentrantReadWriteLock feedReadWriteLock;
上面的创建一个模拟,然后以某种方式必须进入测试中的类。
但是这个:
@InjectMocks
private CustomModule module = mock(CustomModule.class);
是虚假的。 InjectMocks注释的存在是为了做到这一点,并将其变为"部分适合你。
换句话说,你应该做的事情如下:
@Mock
private ReentrantReadWriteLock feedReadWriteLock;
@InjectMocks
private CustomModule module = new CustomModule();
例如,。换句话说:您执行不 模拟您正在测试的类的实例。你创造了一个真实的"实例 - 然后你必须"插入"所需的模拟对象进入即真实实例。 嘲笑被测试的课程绝对没有意义。因为你想测试你的代码,而不是模拟框架为你嘲笑的东西。
InjectMocks注释试图为你做这件事(使用反射和各种黑魔法)。不幸的是,当它无法完成它的工作时,它就会默默地失败。
从这个意义上说,答案是:不要盲目使用东西。您必须完全了解您记下的每一行代码。因此:阅读this以了解这些注释之间的区别。
仅供记录:请注意,您还必须使用Mockito JUnitRunner或手动调用Mockito.initMocks(),以便注释能够发挥其魔力。
答案 1 :(得分:1)
如果您想模拟受测试的课程,则应使用@Spy
。
@RunWith(MockitoJUnitRunner.class)
public class CustomModuleTest {
@Mock
private ReentrantReadWriteLock feedReadWriteLock;
@Spy
@InjectMocks
private CustomModule module;
@Test
public void test() {
doReturn(feedReadWriteLock).when(module).getReadWriteLock();
cacheJob.run();
}
}
请注意,间谍的语法与模拟有点不同。间谍允许您实例化真实对象,但可以根据需要模拟一些方法。
在这里,我返回feedReadWriteLock,其中注释了@Mock
,这样,您就可以更改其行为。您不希望像在示例中那样返回新实例。