Spock 如何为 Java class 模拟相同 class 的方法

Spock how to mock a method of the same class for a Java class

我有一个Javaclass

class MyClass {
  void methodA() {  
         //something 
  }
  void methodB() { 
         //something else 
  }
}

我想对方法 A 进行单元测试,但方法 A 依赖于方法 B。我已经阅读了 spock 文档,但我无法找到如何处理这种情况。我该怎么办?

备注 我找不到这个问题的答案,所以我在 Whosebug 上自行回答这个问题,这是允许的 as per stackoverlfow's self-answering policy。添加此注释是为了避免那些不了解自我回答政策的人感到困惑,因此请勿删除。

一个解决方案是在测试中执行以下操作

def "your spock test"() {
        MyClass myClass = Mock(MyClass)
        myClass.methodA() >> {
            callRealMethod()
        }
        myClass.methodB() >> {
            //your mocking logic
        }
    expect:
        //whatever you want to do
    }

callRealMethod 允许您在通过 spock 模拟时调用实际实现。

这是一种无需模拟重写所需方法的方法:

def "your spock test"() {
    MyClass myClass = new MyClass() {
        @Override
        void methodB() { 
            // do something related to this test
        }    
    }

    expect:
    //whatever you want to do
    myClass.methodA()
}

它实际上记录在 spock 文档中,请参阅部分 partial mocks

// this is now the object under specification, not a collaborator
def persister = Spy(MessagePersister) {
  // stub a call on the same object
  isPersistable(_) >> true
}

when:
persister.receive("msg")

then:
// demand a call on the same object
1 * persister.persist("msg")

我会稍微重新考虑一下这个解决方案,因为你在这里做的是 。我不会嘲笑这个 class 中的任何内容,为了简单起见,我会将其视为一个单元。如果 methodB 表示不同的单元范围,那么 methodA 那么也许这是重构此 class 并将封装在 methodB 中的职责提取到单独的 class 的一个很好的起点注入您要测试的那个。然后嘲笑这个注入 class 在我看来更有意义。但首先总是问问自己为什么要模拟以及是否有更好的选择(模拟应该是你最后一个值得考虑的选择)。