简单的 Mockito 验证在 JUnit 中有效,但在 Spock 中无效
Posted
技术标签:
【中文标题】简单的 Mockito 验证在 JUnit 中有效,但在 Spock 中无效【英文标题】:Simple Mockito verify works in JUnit but not Spock 【发布时间】:2013-05-16 16:47:30 【问题描述】:使用Mockito's examples page 中最基本的示例,我能够在 JUnit 中成功运行。
但是,当我在 Spock 中运行相同的测试时,它失败了。
JUnit/Java 版本(通过):
import org.junit.Test;
import java.util.List;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class SimpleJunitTest
@Test
public void basicMockTest()
List mockedList = mock(List.class);
//using mock object
mockedList.add("one");
mockedList.clear();
//verification
verify(mockedList).add("one");
verify(mockedList).clear();
Spock/Groovy 版本(失败):
import static org.mockito.Mockito.mock
import static org.mockito.Mockito.verify
class SimpleSpockTest extends spock.lang.Specification
def "Basic Mock Test"()
given:
//mock creation
List mockedList = mock(List.class);
when:
//using mock object
mockedList.add("one");
mockedList.clear();
then:
//verification
verify(mockedList).add("one");
verify(mockedList).clear();
这是 Spock 测试失败时出现的错误:
Condition not satisfied:
verify(mockedList).add("one")
| | |
| | false
| $java.util.List$$EnhancerByMockitoWithCGLIB$$172e393a@613043d2 (renderer threw
NullPointerException)
$java.util.List$$EnhancerByMockitoWithCGLIB$$172e393a@613043d2 (renderer threw
NullPointerException)
at SimpleSpockTest.Basic Mock Test(SimpleSpockTest.groovy:25)
有什么想法或建议吗?我真的很喜欢 Spock 和 Mockito,我希望他们能很好地合作。非常感谢!
【问题讨论】:
【参考方案1】:粗略地说,一个 then 块只能包含布尔表达式形式的断言。 Mockito 验证表达式不符合此合约,因为它会在通过时返回一个虚假值(null
、false
、0
),这被 Spock 解释为断言失败。
要解决这个问题,您可以编写一个包裹验证表达式并始终返回 true
的辅助方法,或者您可以使用 Spock 的内置模拟框架代替 Mockito。
【讨论】:
得说,试图避免它,但 Spoke 的模拟验证错误消息非常棒。 谢谢。伟大的错误信息当然是 Mockito 的商标。幸运的是,我经常从 Szczepan(Mockito 的创建者)那里获得关于如何改进 Spock 错误消息的反馈,而且大部分时间我都在听他说什么。 :-) 我会在一段时间后回到这个问题,因为我需要模拟一些 Spring 组件并且仍然无法使用 Spock 模拟来做到这一点,而且我发现Mockito.verify(mock).foo(bar) || true
有效对我来说很好,而且可读性很好。【参考方案2】:
我有一个用例需要 PowerMockito 模拟 Java 类中的最终方法(Spock 模拟不起作用),但还需要验证它们是否被调用,因为最终方法是构建器样式并返回“this” ,即使未调用模拟调用,测试也会通过。
我的解决方案是将“|| true”附加到我的验证调用中,如下所示:
given:
when(myMock.setSomething("xyzzy")).thenReturn(myMock)
when:
def result = objectBeingTested.isExecutedWith("xyzzy")
then:
result == expectedResult
Mockito.verify(myMock).setSomething("xyzzy") || true // this passes
Mockito.verify(myMock).setSomething("wrongValue") || true // this FAILS appropriately
【讨论】:
以上是关于简单的 Mockito 验证在 JUnit 中有效,但在 Spock 中无效的主要内容,如果未能解决你的问题,请参考以下文章
如何在 JUnit Test Java 中替换 Mockito 以存根类
如何使用 Mockito 和 JUnit 在 Spring Boot 中测试 POST 方法