【问题标题】:Spock how to mock a method of the same class for a Java classSpock 如何为 Java 类模拟同一类的方法
【发布时间】:2018-01-09 13:26:45
【问题描述】:

我有一个 Java 类

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

我想对methodA进行单元测试,但是methodA依赖于methodB。我已经浏览了 spock 文档,但我无法找到如何处理这种情况。我该怎么办?

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

【问题讨论】:

    标签: java unit-testing mocking spock


    【解决方案1】:

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

    【讨论】:

      【解决方案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")
      

      【讨论】:

      • 监视已经实例化的对象时是否可以做类似的事情?
      • @schatten 您可以使用实例来创建间谍,但请注意该实例仅用作模板,即复制所有内部状态并创建新的间谍实例。因此,如果其他一些类仍然使用旧实例,您将什么也看不到。
      • 我想问的是:有没有办法监视实例并提供一个闭包来做部分存根。
      • 不,你不能使用闭包(在 Spock 1.x 中),你必须使用定义交互的正常方式。使用 2.x 可以,但它仍处于里程碑阶段。
      【解决方案3】:

      这是一种无需模拟的方式,您可以在其中覆盖所需的方法:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

        • @LeonardBrünings 的答案更适合您的场景!
        猜你喜欢
        • 2020-05-23
        • 2017-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-29
        • 2017-06-29
        • 2014-04-08
        相关资源
        最近更新 更多