【问题标题】:Spock Mocking - my method call values aren't mockedSpock Mocking - 我的方法调用值没有被模拟
【发布时间】:2017-06-19 06:52:33
【问题描述】:

当在我的助手类的静态方法中调用 getMarkup() 时,它会引发 NPE。我所做的是嘲笑 MarkupMaker 及其返回值,即 Markup 的一个实例。最终我想调用标记实例的toString()。无论我做什么——getMarkup() 的调用都在抛出一个 NPE。我找不到任何文档告诉我如何详细模拟 spock 中的方法调用值。

编辑:我添加了示例。 maker.getMarkup() 的调用返回 null 即使我在 spock 测试中嘲笑它。

Test.groovy

class TestExample extends Specification {

    @Shared
    MarkupMaker makerMock = Mock()
    @Shared
    MarkupObject markupMock = Mock()

    def setup() {
        markupMock.toString() >> "headline1"
        makerMock.getMarkup() >> markupMock
    }

    @Unroll
    def "Should return a Markupvalue #expectedvalue"(MarkupMaker helper, int tabElementIndex, String expectedValue) {
        expect:
        MarkupHelper.getMarkupForIndex(helper, tabElementIndex) == expectedValue
        where:
        helper    | tabElementIndex | expectedValue
        makerMock | 1               | "headline1"

    }

}

Helper.java(执行mocked对象的方法)

public class MarkupHelper {

  public static MarkupObject getMarkupForIndex(MarkupMaker maker, int index){
    if(index == 1){
      maker.getMarkup();
    }
    return null;
  }
}

MarkupMaker.java(模拟对象之一)

public class MarkupMaker {

  public MarkupObject getMarkup() {
    return new MarkupObject();
  }
}

MarkupObject.java(保存测试值的最后一个模拟对象)

public class MarkupObject {
  @Override
  public String toString() {
    return "headline1";
  }
}

【问题讨论】:

  • 请发帖MVCE。从这个 sn-p 中并不清楚如何调用有问题的代码。
  • 好的 WIP atm

标签: java mocking spock


【解决方案1】:

删除模拟上的@Shared,因为模拟不支持它。

【讨论】:

    【解决方案2】:

    在您提供的示例中,MarkupHelper 将始终返回 null。您只是调用maker.getMarkup() 而不用它做任何事情。所以会继续执行return null

    Leonard 的答案是正确的,因为您使用 @Shared 为什么您在模拟对象上获得 NPE,但是由于您的 MarkupHelper 实际上没有按照您的预期进行,您的测试仍然不会得到满足。

    同样,您的 MarkupObject 模拟对象是对 toString 进行存根处理,因为当您想使用它时,它会在模拟之外,因此不会被使用。为了处理这个问题,你应该让你的 MarkupHelper 返回一个像这样的字符串:

    public static String getMarkupForIndex(MarkupMaker maker, int index){
        if(index == 1){
            return maker.getMarkup().toString();
        }
        return null;
    }
    

    如果您仍然希望您的 MarkupHelper 返回一个 MarkupObject,那么在您的测试中,您需要创建一个预期的 MarkupObject,它与您的实际属性具有相同的属性。

    【讨论】:

      【解决方案3】:

      我建议在每个测试方法中创建和模拟所有对象。在这种情况下,您将确保每个测试都是独立的,共享数据不会影响您的结果。

      关于您的示例,我将通过这两个测试来介绍 getMarkupForIndex 方法:

      @Unroll
      def "getMarkupForIndex(..) returns null when the given index is #givenIndex"(){
          given:
          def mockedMaker = Mock(MarkupObject)
      
          when:
          def actualResult = MarkupHelper.getMarkupForIndex(mockedMaker, givenIndex)
      
          then:
          actualResult == null
          0 * _._ // no mock interaction at all
      
          where:
          givenIndex << [0, 2, 3]
      }
      
      def "getMarkupForIndex(..) returns a markup object when the given index is 1"(){
          given:
          def expectedMarkupObject = new MarkupObject()
          def mockedMaker = Mock(MarkupMaker) {
              getMarkup() >> expectedMarkupObject
          }
      
          when:
          def actualResult = MarkupHelper.getMarkupForIndex(mockedMaker, 1)
      
          then:
          actualResult.is(expectedMarkupObject)
          1 * mockedMaker.getMarkup()
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-31
        • 1970-01-01
        • 1970-01-01
        • 2016-03-04
        • 2019-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多