使用mockito

时间:2018-02-21 04:53:33

标签: java unit-testing junit mockito powermockito

在我的实现类中,我有一个读写锁定义,如下所示,

@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如何发生这种情况。这样做的理想方法是什么?

2 个答案:

答案 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,这样,您就可以更改其行为。您不希望像在示例中那样返回新实例。