Spock模拟调用被模拟类的真实方法。

问题描述 投票:0回答:1

我有Spock集成测试来测试我的Java应用程序。对于其中一个方法,调用的是真正的方法'bMethod()',而不是返回存根值。对于另一个方法'aMethd()',它工作得很好,而且返回的是存根值,而实际的方法没有被调用。这两个方法都在同一个类中,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
    }
}
java spock
1个回答
0
投票

试试这样的方法

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

需要注意的地方。

  • 推送到stub上的返回值应该是返回的内容,而不是闭包。

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

  • 你在数学上调用的方法不需要参数。


0
投票

前言

我把你编辑之前的原问题的代码抄了下来,至少能让你的代码更合理一些。请你 从来没有 在没有运行它并检查它是否能重现问题的情况下发布示例代码。伪代码对任何人都没有帮助,对试图回答你的问题的社区没有帮助,对你自己也没有帮助,因为你只会引起疯狂的猜测,而不是得到正确的答案。在生活中,这个原则也同样适用于编程:垃圾进,垃圾出。

原创代码与最小的修复

所以我先做了 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
...

失败的原因是你没有在任何地方注入你的mock,但是... ... Math 使用硬编码的 Calc 例子 Calc calc = new Calc().

使测试合格

所以我们需要一种方法来注入mock,例如通过构造函数或setter。你也应该把字段类型从 CalcCalcIntf 因为否则无法注入接口mock。如果你的代码中不使用接口,而是针对具体的子类进行编码,为什么要创建接口呢?

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,这意味着实现mock的动态代理不能覆盖它,从而不能存根。但这与你在代码中描述的情况完全不同。

看到了吗?你的示例代码是 一文不值 如果它不能重现问题,这就是为什么我在评论中告诉你要始终提供一个 MCVE 而不是一些随意的伪代码。一个专业的软件开发者没有理由这么懒惰。如果有人报告你的代码有bug,你也想知道如何重现。对不起,在这里教训你,但你需要有一些作为开发者的职业自豪感,学会如何提问。

所以为了重现你所报告的这样一个问题,我不得不做一个有根据的猜测,因为你的代码是没有用的。只要在上一个版本中修改以下内容就可以了。

  • int bMethod(int a, int b, int c)final int bMethod(int a, int b, int c)
  • Mock(CalcIntf)Mock(Calc) 两处

现在测试结果是:一个合格,一个不合格的功能方法。

Condition not satisfied:

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

希望对你有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.