我使用了dart unittest框架和包含的Mock类as described
然而,模拟调用存在依赖性,即:
..store.when(callsTo('isLocked')).thenReturn(false);
通过名称调用isLocked
方法的调用。如果有人重命名了isLocked
方法,重构框架将不会重命名该调用。
我想知道反射(镜像)是否能以某种方式提供帮助,但我还没有找到解决方案。
干杯 彼得
答案 0 :(得分:1)
作为一般规则,我试图避免模拟类(除非他们使用外部资源,如RESTful Web API),因为这个问题。如果A类模仿了B类的foo方法,但是B类实际上已经重命名了它的foo方法fooBar,那么你的测试仍然会通过。但是,当A类试图在运行时调用B.foo时,事情就会崩溃。因此,我避免嘲笑当地可用的任何东西。
幸运的是,Dart的情况比其他动态语言要好一些。例如,您可以创建一个实现另一个类的类。因此,如果FakeB实现B,那么您可以向FakeB添加可在测试A时使用的函数。
当然,重构框架知道您的代码调用To('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”不作为函数存在,它将会爆炸。它有点丑陋和hacky,但它正朝着你想要的方向发展。
你可以做的另一件事是:
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"));
}
这可以让你写一些类似于callTo(makeSureItExists(login,“login”))。
答案 1 :(得分: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();
}
我的优点是简单明了。我倾向于那个。
欢呼声 彼得