繁体   English   中英

Spock mock调用mocked class的真实方法

[英]Spock mock calling real method of mocked class

我有 Spock 集成测试来测试我的 Java 应用程序。 对于其中一种方法,调用将转到真正的方法“bMethod()”,而不是返回存根值。 它适用于另一种方法'aMethd()',并且返回存根值并且不调用实际方法。 这两种方法都在相同的 class,Calc。 有没有办法调查 Spock 在做什么以及为什么?

public interface CalcIntf {
  public int aMethod(int a, int b);      
  public int bMethod(int a, int b, int c);
}

MyTestSpec extends Specification {
    def "aMethod test"() {
        given:
          ...
          CalcIntf calcIntf = Mock(CalcIntf)
          calcIntf.aMethod(_,_) >> { return 100; }
        when:
          //service call
        then:
          // asserts go here
    }

    def "bMethod test"() {
        given:
          ...
          CalcIntf calcIntf = Mock(CalcIntf)
          calcIntf.bMethod(_,_,_) >> { return 100; }
        when:
          // service call
        then:
          // asserts go here
    }
}

尝试类似的东西

given: 'a math with a calculator that always returns 100'
    def calc = Stub(CalcIntf) {
        bMethod(_,_,_) >> 100
    }
    def math = new Math(calc)

when: 'the math is asked to calculate something'
    def result = math.m2()

then: 'it returns 100'
    result == 100

注意事项:

  • 推送到存根上的返回值应该是返回的而不是闭包

  • 您必须通过构造函数或其他方式在数学中设置存根计算

  • 您在数学上调用的方法不采用 arguments

具有最少修复的原始代码

所以首先我让m1m2返回int而不是void 然后至少你可以检查结果。 然后我还确保在没有参数的情况下正确调用这些方法,正如 Chris 已经提到的那样。 所以现在代码看起来像这样:

package de.scrum_master.stackoverflow.q62269054

import spock.lang.Specification

class MyTestSpec extends Specification {
  def "testing addition using aMethod"() {
    given:
    Math math = new Math()
    CalcIntf calcIntf = Mock(CalcIntf)
    calcIntf.aMethod(_, _) >> { return 123 }
    expect:
    math.m1() == 123
  }

  def "testing addition using bMethod"() {
    given:
    Math math = new Math()
    CalcIntf calcIntf = Mock(CalcIntf)
    calcIntf.bMethod(_, _, _) >> { return 456 }
    expect:
    math.m2() == 456
  }

  interface CalcIntf {
    int aMethod(int a, int b)

    int bMethod(int a, int b, int c)
  }

  static class Calc implements CalcIntf {
    int aMethod(int a, int b) {
      return a + b
    }

    int bMethod(int a, int b, int c) {
      return a + b + c
    }
  }

  static class Math {
    Calc calc = new Calc()

    int m1() {
      calc.aMethod(1, 2)
    }

    int m2() {
      calc.bMethod(1, 2, 3)
    }
  }
}

当然,测试失败:

Condition not satisfied:

math.m1() == 123
|    |    |
|    3    false
...

Condition not satisfied:

math.m2() == 456
|    |    |
|    6    false
...

失败的原因是你没有在任何地方注入你的模拟,但是Math通过Calc calc = new Calc()使用了一个硬编码的Calc实例。

使测试通过

所以我们需要一种注入模拟的方法,例如通过构造函数或设置器。 您还应该将字段类型从Calc更改为CalcIntf ,否则无法注入接口模拟。 如果您不在代码中使用接口而是针对具体子类编写代码,为什么还要创建接口?

package de.scrum_master.stackoverflow.q62269054

import spock.lang.Specification

class MyTestSpec extends Specification {
  def "testing addition using aMethod"() {
    given:
    CalcIntf calcIntf = Mock(CalcIntf)
    calcIntf.aMethod(_, _) >> { return 123 }
    Math math = new Math(calcIntf)
    expect:
    math.m1() == 123
  }

  def "testing addition using bMethod"() {
    given:
    CalcIntf calcIntf = Mock(CalcIntf)
    calcIntf.bMethod(_, _, _) >> { return 456 }
    Math math = new Math(calcIntf)
    expect:
    math.m2() == 456
  }

  interface CalcIntf {
    int aMethod(int a, int b)

    int bMethod(int a, int b, int c)
  }

  static class Calc implements CalcIntf {
    int aMethod(int a, int b) {
      return a + b
    }

    int bMethod(int a, int b, int c) {
      return a + b + c
    }
  }

  static class Math {
    CalcIntf calcIntf

    Math(CalcIntf calcIntf) {
      this.calcIntf = calcIntf
    }

    int m1() {
      calcIntf.aMethod(1, 2)
    }

    int m2() {
      calcIntf.bMethod(1, 2, 3)
    }
  }
}

您描述的测试行为

所以现在测试通过了,但它们不会重现您描述的行为:

对于其中一种方法,调用将转到真正的方法“bMethod()”,而不是返回存根值。

我可以想象会发生这种情况的一个原因:您要存根的方法是final ,这意味着实现模拟的动态代理不能覆盖它,因此不能存根它。 但这与您在代码中描述的情况完全不同。

看? 如果您的示例代码不能重现问题,那么它就完全没用,这就是为什么在我的评论中我告诉您始终提供MCVE而不是一些随机的伪代码。 如果有人报告了您的代码中的错误,您还想知道如何重现它。

因此,为了重现您报告的问题,我必须做出有根据的猜测,因为您的代码没有帮助。 只需在以前的版本中更改以下内容:

  • int bMethod(int a, int b, int c)final int bMethod(int a, int b, int c)
  • Mock(CalcIntf)Mock(Calc)在 2 个地方

现在测试结果是:一种通过,一种失败的特征方法:

Condition not satisfied:

math.m2() == 456
|    |    |
|    6    false
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM