Spock间谍/模拟未注册调用

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

我的测试类中有一个仅调用其他两个方法的方法。我正在尝试编写一个测试,检查这两个方法是否实际被调用,但是没有注册任何调用。我正在测试的Java代码:

    public void populateEdgeInfo(Map<Actor, SchedulableNode> knownNodes) {
        populateDestinationInfo(knownNodes);
        populateSourceInfo(knownNodes);
    }

我的测试代码:

def "Populating edge info means both source and destination information will be populated" () {
    given:
    actor.getDstChannels() >> []
    actor.getSrcChannels() >> []
    SchedulableNode schedulable = Spy(SchedulableNode, constructorArgs: [actor])

    when:
    schedulable.populateEdgeInfo([:])

    then:
    1 * schedulable.populateDestinationInfo(_)
    1 * schedulable.populateSourceInfo(_)
}

唯一注册的是对populateEdgeInfo的调用。我做错了什么吗?也尝试使用Mock而不是Spy无效。

java unit-testing testing groovy spock
1个回答
0
投票

我试图根据您的稀疏信息创建一个MCVE,但在您的测试中未发现任何问题:

package de.scrum_master.stackoverflow.q60926015;

import java.util.List;

public class Actor {
  public List getDstChannels() {
    return null;
  }

  public List getSrcChannels() {
    return null;
  }
}
package de.scrum_master.stackoverflow.q60926015;

import java.util.Map;

public class SchedulableNode {
  private Actor actor;

  public SchedulableNode(Actor actor) {
    this.actor = actor;
  }

  public void populateEdgeInfo(Map<Actor, SchedulableNode> knownNodes) {
    populateDestinationInfo(knownNodes);
    populateSourceInfo(knownNodes);
  }

  public void populateDestinationInfo(Map<Actor, SchedulableNode> knownNodes) {}

  public void populateSourceInfo(Map<Actor, SchedulableNode> knownNodes) {}
}
package de.scrum_master.stackoverflow.q60926015

import spock.lang.Specification

class SchedulableNodeTest extends Specification {
  def actor = Mock(Actor)

  def "Populating edge info means both source and destination information will be populated"() {
    given:
    actor.getDstChannels() >> []
    actor.getSrcChannels() >> []
    SchedulableNode schedulable = Spy(SchedulableNode, constructorArgs: [actor])

    when:
    schedulable.populateEdgeInfo([:])

    then:
    1 * schedulable.populateDestinationInfo(_)
    1 * schedulable.populateSourceInfo(_)
  }
}

这意味着您的代码必须不同于我的代码。 我的猜测是,这两个populate*方法都在您的类中是private这使得无法模拟它们,因为模拟使用动态代理,而后者在技术上是子类。但是,子类看不到私有超类方法,因此动态代理无法拦截(调用)它们。

可能的解决方案:

  • 停止过度指定测试并测试内部交互。它使测试变得脆弱,如果还要重构被测类,则必须经常对其进行重构。

  • 如果public不正确,则使populate*方法受到保护或以包为范围。然后,您可以对它们进行存根并检查它们之间的交互。

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