java - Spock Spy/Mock 未注册调用

标签 java unit-testing testing groovy spock

我的测试类中有一个方法,它只调用另外两个方法。我正在尝试编写一个测试来检查这两个方法是否确实被调用,但没有注册任何调用。 我正在测试的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,但无济于事。

最佳答案

我尝试创建一个 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)这使得不可能模拟它们,因为模拟使用动态代理,而后者从技术上讲是子类。但是,子类看不到私有(private)父类(super class)方法,因此动态代理无法拦截(调用)它们。

可能的解决方案:

  • 停止过度指定您的测试和测试内部交互。它使测试变得脆弱,如果您还重构被测类,则必须经常重构它。

  • 如果 public 不正确,请将 populate* 方法设为 protected 或在包范围内。然后您可以 stub 它们并检查它们的交互。

关于java - Spock Spy/Mock 未注册调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60926015/

相关文章:

java - 对象序列化为 json,仅限某些字段

java - 使用 JUnit 对 Java 中 Daemon Thread 的代码进行单元测试

ruby-on-rails - Rails 3.1、rspec、guard 和 spork 在 Windows 上真的很慢

android - 在 beta/alpha 测试期间安装实际版本 (Android)

java - 将 HTML 表单数据发送到 Java

java - Spring Boot从命令行读取属性文件无法解析占位符 'ConfigPath'

项目类路径测试中缺少 java ee api

selenium -//按钮[@type ='submit']意思

java - 渲染图像不显示 Java Libgdx

c# - 带静态值的单元测试