【问题标题】:Mockito - Stubbing a method of an object that was returned by a mock object methodMockito - 存根由模拟对象方法返回的对象的方法
【发布时间】:2011-12-17 18:03:00
【问题描述】:

假设我有一个模拟对象,我不想存根它的任何方法,但我想存根它返回的对象的方法。例如,

when(mockObject.method1()).thenReturn(returnValue)

是平时怎么做的,不过我在找,

when(mockObject.method1().method2()).thenReturn(returnValue)

这可能吗?如果我这样做,我会得到一个 NullPointerException。目前我已经存根第一个方法来返回一个模拟对象,然后使用返回的模拟对象存根第二个方法。但是,这些临时模拟对象对我来说毫无用处,并且在将许多方法链接在一起之后,会产生很多无用的模拟对象。

编辑:实际上,链接可能有效,但我的对象导致了 NPE。此代码(第一行)导致 NPE:

when(graphDb.index().getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

但是这段代码有效:

IndexManager indexManager = mock(IndexManager.class);
when(graphDb.index()).thenReturn(indexManager);
when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);

因此,链接对于返回 AutoIndexer 对象的 getNodeAutoIndexer() 不起作用,而对于返回 RelationshipAutoIndexer 的 getRelationshipAutoIndexer() 起作用。两个返回值都被模拟如下:

nodeAutoIndexer = (AutoIndexer<Node>) mock(AutoIndexer.class);
relAutoIndexer = mock(RelationshipAutoIndexer.class);

那么可能导致问题的原因是什么?

【问题讨论】:

    标签: java mockito method-chaining stubbing


    【解决方案1】:

    完全没有问题。

    让我们检查一下这 4 行代码:

    IndexManager indexManager = mock(IndexManager.class);
    when(graphDb.index()).thenReturn(indexManager);
    when(indexManager.getNodeAutoIndexer()).thenReturn(nodeAutoIndexer);
    when(graphDb.index().getRelationshipAutoIndexer()).thenReturn(relAutoIndexer);
    

    第一行创建了一个模拟 indexManager。

    第二个告诉 mock graphDb 在调用 index 方法时返回 indexManager(在第一行创建的 mock)。

    第三个告诉模拟 indexManager(在第一行创建)在调用其 getNodeAutoIndexer 方法时返回 nodeAutoIndexer。

    最后一行调用 graphDb.index(),它返回模拟 indexManager(你在第二行告诉它这样做),并要求这个 indexManager(这是你在第一行创建的模拟)在什么时候返回 relAutoIndexer它的 getRelationshipAutoIndexer 方法被调用。

    最后一行之所以有效,只是因为您告诉模拟 graphDb 在调用其 index 方法时要返回什么。如果您之前没有这样做过,那么模拟的 graphDb.index() 方法将返回 null 并且您将拥有 NPE。

    【讨论】:

    • 谢谢。所以假设我有一个很长的函数链,我是否必须重复这个对每个函数进行存根的过程?没有存根 index() 就没有办法让 NPE 工作的代码吗?我觉得 Mockito 应该以某种方式根据函数的返回类型自动使用模拟对象对这些方法进行存根,这样我就不必为我不需要的直接存根函数而烦恼。我只需要这些功能即可使用其他功能...
    • 没有。对于返回对象的方法,默认返回值为 null。恕我直言,您遇到的问题表明您违反了得墨忒耳的法律:不要与陌生人交谈。
    • 请注意,mockito 提供了一个深度存根功能 (mock(LegacyType.class, RETURNS_DEEP_STUBS)),但不鼓励使用它,因为您可能会违反 good design 法则,例如 Demeter 法则。另请注意,此功能尚不适用于泛型类型,例如 List。
    • 谢谢布莱斯。我不知道,这实际上可以解决 OP 的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多