【问题标题】:Ho do I mock external functions used in recursive functions?如何模拟递归函数中使用的外部函数?
【发布时间】:2017-07-04 14:34:04
【问题描述】:

以这个函数为例:

public static int[] mergeSort(int[] array, int lo, int hi) {
        if (lo == hi) {
            return array;
        }
    int mid = (lo + hi) / 2;
    mergeSort(array, lo, mid);
    mergeSort(array, mid, hi);
    merge(array, lo, mid + 1, hi);

    return array;
}

如您所见,我想在测试中模拟函数merge。 有可能吗?

【问题讨论】:

  • 可以使用间谍!在此处查看示例 (stackoverflow.com/questions/4860475/…)。但是一些测试框架不支持对静态方法的监视!
  • 静态方法的单元测试往往笨拙且脆弱。模拟框架的局限性使其成为不可能。您最好将此作为实例方法并将merge 作为依赖项注入。那么单元测试就非常简单和健壮了。

标签: java unit-testing recursion


【解决方案1】:

大概是这样。但这是错误的想法!

您想测试 sort 方法。如果你认为你需要嘲笑,那你就做错了!

该方法接受一个数组并且应该返回相同的数组 - 只是排序。

因此,您的测试应该使用它:传入一个数组 - 并检查输出是否符合预期!你绝对不在乎里面发生了什么。您专注于测试 what,而不是 如何

所以你的测试看起来像:

@Test
public void testReverseArray() {
  assertThat(Whatever.mergeSort(new int[] { 3, 2, 1 }), is(new int[] { 1, 2, 3 });
}

例如(其中hamcrest matcher)。

换句话说:如果您认为您必须“排除”对 static 方法的调用 - 那么您可能正在这样做,因为调用真正的方法会给您带来各种麻烦。

所以你必须在测试这个方法时“模拟”它。但令人惊讶的是,当您测试调用外部 mergeSort() 方法的方法时,您还必须摆脱它。

因此:

  • 在使用 static 关键字时要非常小心
  • 一旦你发现调用一个静态方法在单元测试中变成了一个问题:把它作为你必须重做那个方法的明确证据

含义:应该重新编写 static 调用以允许在单元测试中调用它 - 或者去掉 static 修饰符。

【讨论】:

  • 如果merge 有问题,合并测试应该失败,而不是mergeSort 测试,不是吗?如果我们在Unit Testing 土地上。
  • @Cristian 取决于。如果该方法是private,那么您就不要单独对其进行测试。如果您有充分的理由将其公开,那么您当然有专门的合并测试用例。但是:即使是这样:在测试mergeSort() 时试图“删掉”merge() 是错误的方法;如上所述。
【解决方案2】:

谢谢各位, 我想mock的原因是:

假设如下:

  • 这个函数,merge(或任何一个)将在 100 个函数中使用
  • 修改合并导致意外结果
  • 100 个测试失败,因为 merge 失败。
  • 我们有 100 个测试失败,而不是测试 merge 函数的测试失败,因为 merge 失败了。

【讨论】:

  • 这是有道理的。
猜你喜欢
  • 1970-01-01
  • 2019-06-16
  • 2020-05-23
  • 2021-07-19
  • 2011-07-14
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
相关资源
最近更新 更多