Spock如何为Java类模拟同一个类的方法

时间:2017-08-02 10:52:13

标签: java unit-testing mocking spock

我有一个Java类

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

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

注意 我无法找到答案,所以我在stackoverflow上自我回答这个问题,允许as per stackoverlfow's self-answering policy。添加此注释以避免混淆那些不了解自我回复政策的人,所以不要删除。

4 个答案:

答案 0 :(得分:2)

这是一种无需模拟覆盖所需方法的方法:

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()
}

答案 1 :(得分:2)

实际上已在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")

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

我会稍微重新考虑这个解决方案,因为你在这里做的是you are testing mock instead of a real object。我不会在这个类中嘲笑任何东西,我会把它当作一个简单的单元。如果methodB代表不同的单位范围,那么methodA那么这可能是重构这个类并将methodB中封装的职责提取到一个单独的类中的一个很好的起点,该类注入到您正在尝试的那个测试。然后嘲笑这个注入的课程在我看来更有意义。但首先总是问自己为什么要嘲笑,如果有更好的选择(嘲笑应该是你最后的选择值得考虑)。