如何在Dart中测试私有函数?

Fre*_*ind 16 dart dart-unittest

假设我在dart文件中定义了一个私有函数hello.dart:

_hello() {
  return "world";
}
Run Code Online (Sandbox Code Playgroud)

我想在另一个文件中测试它mytest.dart:

library mytest;

import 'dart:unittest/unittest.dart';

main() {
  test('test private functions', () {
    expect(_hello(), equals("world"));
  }
}
Run Code Online (Sandbox Code Playgroud)

但不幸的是,测试代码无法编译.但我确实需要测试那个私有_hello函数.有什么解决方案吗?

Dan*_*eld 11

虽然我同意私有方法/类不应该是您的测试的一部分,但是meta包确实提供了一个@visibleForTesting属性,如果您尝试使用其原始库之外的成员或测试,分析器将向您发出警告.你可以像这样使用它:

import 'package:meta/meta.dart';
...
@visibleForTesting
hello() {
    return "world";
}
Run Code Online (Sandbox Code Playgroud)

您的测试现在可以使用它而不会出现错误或警告,但如果其他人尝试使用它,他们会收到警告.

再一次,关于做到这一点的智慧是另一个问题 - 通常如果这是值得测试的东西,它是值得公开的东西(或者它将通过你的公共接口进行测试,这无论如何真正重要).与此同时,您可能只想拥有严格的测试或测试驱动原则,即使对于您的私有方法/类也是如此--Dart会让您这样做.

  • 抱歉,但我不同意“值得测试的东西值得公开”的说法。按照这种逻辑,没有任何获取、映射、处理等方法值得测试,因为在大多数情况下没有理由将它们公开。但这意味着,我必须运行 90% 的“公共”代码才能测试一个嵌套的私有方法,我什至可能无法直接验证其结果,因为它在途中被丢弃。直接测试私有方法似乎比通过评估其间接影响来确定它是否正常工作更有效。 (2认同)

gtu*_*rri 10

有些人认为我们不应该直接测试私有:它应该通过公共接口进行测试.

遵循本指南的一个优点是,您的测试不依赖于您的实施.换句话说:如果你想改变你的私人而不改变你向世界揭露的东西,那么你就不必触摸你的测试.

根据这所学校的说法,如果你的私人足够重要,可以证明单元测试的合理性,那么在新课程中提取它是有意义的.

将所有这些放在一起,你在这里可以做的是:

  • 使用此hello方法创建一种帮助类为public.然后,您可以轻松地进行单元测试
  • 让您当前的类使用此辅助类的实例
  • 测试当前类的公共方法依赖于_hello:如果这个私有错误,它应该被那些更高级别的测试捕获

  • 我被强制语言的封装所迫使遵循这条规则(就像我们大多数人一样),我不相信这是一个充分的理由,因为私有方法可能会变得混乱,复杂,递归等等.所以对于OP,我建议你确实将这些东西提取到一个新的类中,并保留重复样板的私有(当然,直到你遇到这个规则的例外).这将是一个很好的机会,使您的代码具有通用性,抽象性,并在编写高质量代码时满足我们所有人喜爱的所有最佳实践. (3认同)
  • 我讨厌这所学校,我还需要测试私有方法 (2认同)

use*_*671 9

我不喜欢以上两个答案。dart 的私有变量测试设计非常糟糕。dart 的私有可见性是基于库的,并且每个 .dart 文件默认都是一个库,类似的语言是 Rust,但是 rust 可以直接在文件中编写测试代码,不存在私有可见性问题,而 dart 不允许这样做。

再说一遍,我不认为@visibleForTesting是一个有效的解决方案,因为@visibleForTesting只能用来装饰公共声明,它只是作为一个分析提醒,开发人员不能在其他文件中调用这些声明,但是从语法的角度来看,开发者也不能使用_前缀,因此public、private的形式变得混乱。并且违反了 dart 自己的命名规则。

不应该测试私有的,或者应该将它们分成其他类的论点,就像是一种完全不可接受的理由。

首先,私有之所以存在,是因为它们在上下文关系中属于业务逻辑/模型等,将其分离到另一个类中没有逻辑意义。

其次,如果你必须这样做,将会大大增加代码的复杂性,例如,你移动到其他类将失去对上下文变量的访问,或者你必须传递一个单独的引用,或者必须创建一个实例类,确实,那么你终于可以做一些模拟了,但是你也添加了一个抽象层,很难想象如果你要为整个项目这样做,你可能会将整个代码层加倍。

目前,如果你希望你的 dart 包获得超过 90% 的覆盖率,你不应该定义任何 private。

听起来很刺耳,但这就是真实的故事。

[替代] 好像还没人提到这个,

使用part/part of来暴露私有,您可以定义一个特定于测试的.dart文件作为要测试的库(文件)的公共接口,并使用它来暴露所有需要测试的私有声明。你可以将它们命名为xxx.fortest.dart

但这更多的是一种心理解决方案,因为您本质上仍然暴露了所有私有变量/方法

但至少,它比拆分类要好,而且,如果有一天 dart 最终解决了这个问题,我们可以简单地删除这些.fortest.dart文件。