1

我已经使用了 dart unittest 框架和所描述的包含的 Mock 类

然而,模拟调用中存在依赖关系,即:

..store.when(callsTo('isLocked')).thenReturn(false);

其中对isLocked方法的调用是按名称调用的。如果有人重命名该isLocked方法,重构框架将不会重命名该调用。

我想知道反射(镜子)是否可以以某种方式提供帮助,但我还没有找到解决方案。

干杯彼得

4

2 回答 2

1

作为一般规则,我尽量避免模拟类(除非它们使用外部资源,如 RESTful Web API),特别是因为这个问题。如果 A 类模拟了 B 类的 foo 方法,但 B 类实际上重命名了它的 foo 方法 fooBar,你的测试仍然会通过。但是,当 A 类尝试在运行时调用 B.foo 时,事情就会崩溃。因此,我避免嘲笑任何本地可用的东西。

幸运的是,在 Dart 中的情况比在其他动态语言中要好一些。例如,您可以创建一个实现另一个类的类。所以如果 FakeB 实现了 B,那么你可以在 FakeB 中添加可以在测试 A 时使用的函数。

自然,重构框架知道您的代码 callTo('isLocked') 实际上引用了一些名为 isLocked 的方法,而实际上该方法已重命名为 isReallyLocked,这有点过头了。但是,我认为您在查看镜像 API 时走在正确的道路上。例如,如果您可以编写 callTo(isLocked.name ),那就太好了。这样,VM 可以为您的模拟提供更多检查。

自然,真正的目标是在 API 不匹配时让测试失败。我玩了一些镜像 API,我能想到的最好的方法是:

#import('dart:io');
#import("dart:mirrors");

void a() {
  print("a");
}

void main() {
  String thisFile = "file://${new Directory.current().path}/${new Options().script}";
  print(currentMirrorSystem().libraries[thisFile].functions['a'].simpleName);
}

这段代码仍然使用“a”作为字符串,但它的好处是如果“a”不作为函数存在,它会爆炸。这有点丑陋和骇人听闻,但它正朝着你所寻找的方向发展。

您可以做的另一件事是:

when(callsTo('isLocked')).alwaysCall(isLocked)

在这种情况下,模拟系统只是在调用者和 isLocked 函数之间扮演一个中间人。这种方法有两个缺点:a) 大概您试图完全避免调用 isLocked,否则您将不会使用模拟框架 b) isLocked 是重复的,首先作为字符串,然后作为函数。但是,它确实有几个好处:a)它可以让您记录 isLocked 被调用的事实 b)如果 isLocked 被重命名,它将不起作用;即重命名 isLocked 的人将看到此代码,并希望更新这两个地方。

另一种“蛮力”方法如下:

void a() {
  print("a");
}

String makeSureItExists(obj, String name) {
  return obj != null ? name : "NoSuchMethod";   
}

void main() {
  print(makeSureItExists(a, "a"));
}

这使您可以编写类似callsTo(makeSureItExists(login, "login")) 的内容。

于 2012-09-12T21:15:30.740 回答
0

好吧,我最终使用的方法是一个带有方法名称的常量类。像这样:

class MethodNames{
  final String GET_ELEMENT = 'getElement';
  final String GET_CLASSES = 'get classes';
  final String SET_DISABLED = 'set:disabled';
  final String AS_INPUT = 'asInput';
  final String AS_BUTTON = 'asButton';
  final String SET_INNER_HTML = 'set:innerHTML';
  final String SET_VALUE = 'set:value';
...
  const MethodNames();
}

我的优点是既漂亮又简单。我倾向于这样。

欢呼彼得

于 2012-11-20T11:22:47.310 回答