2012-11-20 118 views
9

我用Mockito嘲笑一个对象,这个对象上的同一个方法被多次调用,我想每次都返回相同的值。
这是我有:Mockito:多次调用相同的方法

LogEntry entry = null; // this is a field 
// This method is called once only. 
when(mockLogger.createNewLogEntry()).thenAnswer(new Answer<LogEntry>() { 
    @Override 
    public LogEntry answer(InvocationOnMock invocationOnMock) throws Throwable { 
    entry = new LogEntry(); 
    return entry; 
    } 
}); 
// This method can be called multiple times, 
// If called after createNewLogEntry() - should return initialized entry. 
// If called before createNewLogEntry() - should return null. 
when(mockLogger.getLogEntry()).thenAnswer(new Answer<LogEntry>() { 
    @Override 
    public LogEntry answer(InvocationOnMock invocationOnMock) throws Throwable { 
    return entry; 
    } 
}); 

的问题是,似乎我的getLogEntry方法被调用一次。对于所有后续调用,返回null,而我在测试中得到NPE。
如何告诉mockito对所有呼叫使用stubbed版本?

============================================== ===================
验尸子孙后代

我做了一些额外的调查,并一如既往它不是图书馆的错,是我的错。在我的代码之前调用createNewLogEntry()之前调用getLogEntry()的方法之一。 NPE是绝对合法的,测试实际上在我的代码中发现了一个错误,而不是我在Mockito中发现错误。

+0

很神秘。一般来说,这应该起作用。我想我会提出几个问题:1)你确定它是空的条目,而不是以某种方式将mockLogger重置为空吗? 2)是否有可能mockLogger正在重新创建没有嘲笑的方法?在定义它的方法中设置上面的代码(安装与测试方法)可能会有所帮助。最后,你可以在你的答案impl(或断点)中试试println,以确定实际执行的是什么。 –

+0

试图重现你的问题,类似的方法适用于我使用Mockito 1.9.5 ==>也许你可以通过Mockito邮件列表发送整个测试类的代码? – s106mo

回答

10

您的存根应该按照您的要求工作。从Mockito doc

一旦存根,该方法将总是返回存根值,而不管 它被调用多少次。

+0

我纠正了这个问题,我实际上使用了thenAnswer()。 –

1

我错过了什么,或者会满足以下要求吗?

LogEntry entry = null; // this is a field 
when(mockLogger.createNewLogEntry()).thenAnswer(new Answer<LogEntry>() { 
    @Override 
    public LogEntry answer(InvocationOnMock invocationOnMock) throws Throwable { 
    if (entry == null) { 
     entry = new LogEntry(); 
    } 
    return entry; 
    } 
}); 
when(mockLogger.getLogEntry()).thenAnswer(new Answer<LogEntry>() { 
    @Override 
    public LogEntry answer(InvocationOnMock invocationOnMock) throws Throwable { 
    return entry; 
    } 
}); 

只做entry == null的分配。

+0

createNewLogEntry()仅被调用一次。之后,可以多次调用getLogEntry(),但似乎只有一次调用模拟版本,然后返回默认值null。 –

+2

看起来像奇怪的事情正在发生。每次调用方法时,Mockito都应该调用Answer。你确定你没有在你的代码/测试中重置模拟或入口吗? –

+0

我检查了,我设置的entry = null的唯一地方是在setUp()方法中,如上所示。我不会在测试中的任何地方重置它。我会做更多的调试,但据我所知,getLogEntry()的回答只被调用一次。明天我会进行更多的调查。 –

4

除非我失去了一些东西,如果你想返回每个方法调用同一个对象,那么为什么不单纯做:

final LogEntry entry = new LogEntry() 
when(mockLogger.createNewLogEntry()).thenReturn(entry); 
when(mockLogger.getLogEntry()).thenReturn(entry); 

... 

verify(mockLogger).createNewLogEntry(); 
verify(mockLogger, times(???)).getLogEntry(); 

会的Mockito返回每个匹配调用相同的值。

+0

如果首先调用createNewLogEntry(),则对getLogEntry()的所有后续调用应返回初始化条目。如果不先调用createNewLogEntry(),则后续对getLogEntry()的调用应该返回null。你提出的建议不会以这种方式工作。 –

+1

如果可能的话,你能把它分成两个单独的测试用例吗?其中'createNewLogEntry'被称为另一个时,其中一个不是?这可能会简化事情。 – Jonathan

+1

我相信你的意思是'thenReturn',而不是'thenAnswer'。 –