不可否认,这是一个奇怪的测试案例,但这是我遇到的一个问题。我有一个类,它在一个构造函数中将函数作为参数。我想知道传递的函数是否被调用。这是一个例子:
class TestClassMock extends Mock implements RealClass {
RealClass _real;
TestClassMock() {
_real = new RealClass();
when(callsTo("myNamedFunction")).alwaysCall(_real.myNamedFunction);
}
}
class RealClass {
String _name = "RealClass";
Function myNamedFunction;
RealClass() {
myNamedFunction = _theNamedFunction;
}
String _theNamedFunction() {
return _name;
}
}
class ClassThatCallsRealClass {
ClassThatCallsRealClass(Function func) {
func();
}
}
//The test
TestClassMock testClassMock = new TestClassMock();
ClassThatCallsRealClass caller = new ClassThatCallsRealClass(testClassMock.myNamedFunction);
testClassMock.getLogs(callsTo("myNamedFunction")).verify(happenedOnce);
所以为了解释一下,ClassThatCallsRealClass将一个函数作为参数并调用它。如果您要传入(Instance Of RealClass).myNamedFunction,则会依次调用RealClass上的私有函数_theNamedFunction。但是,如果您尝试模拟RealClass并将myNamedFunction中的所有调用重定向到RealClass myNamedFunction,则这似乎失败了。我没有看到任何明确的方法来实现这一点,但我认为这是可能的。
有什么想法吗?
答案 0 :(得分:2)
在Dart中,所有函数都是类Function
的实例,因为您将Function
的实例传递给ClassThatCallsRealClass
构造函数。 Function
的实例有一个方法call()
,如here所示。
与此同时,Dart具有非常好的模拟功能here(感谢@KWalrath的更新)。
所以你需要做的就是测试与其他任何对象一样的模拟。正如引用中所述,为ClassThatCallsRealClass
创建一个间谍,为Function
实例创建一个模拟。然后在函数的verify(happenedOnce)
方法上使用call()
。
要模拟你的功能,请执行以下操作:
class MockFunction extends Mock {
call(int a, int b) => a + b;
}
var mock = new MockFunction();
mock(1,2); //returns 3
当然,call
的参数列表将匹配实际函数的参数列表。在mock
上将ClassThatCallsRealClass
传递给您的间谍。
答案 1 :(得分:1)
这对我有用:
library x;
import "package:unittest/unittest.dart";
import "package:unittest/mock.dart";
class TestClassMock extends Mock implements RealClass {
RealClass _real;
TestClassMock() {
_real = new RealClass();
when(callsTo("myNamedFunction")).alwaysCall(_real.myNamedFunction);
}
}
class RealClass {
String _name = "RealClass";
Function myNamedFunction;
RealClass() {
myNamedFunction = _theNamedFunction;
}
String _theNamedFunction() {
return _name;
}
}
class ClassThatCallsRealClass {
ClassThatCallsRealClass(Function func) {
func();
}
}
class MyFunc implements Function {
Function func;
String functionName;
MyFunc(this.func, this.functionName);
call() {
var inv = new MyInvocation(functionName);
func(inv);
}
}
main(List<String> args) {
test('xx', () {
//The test
TestClassMock testClassMock = new TestClassMock();
ClassThatCallsRealClass caller = new ClassThatCallsRealClass(new MyFunc(testClassMock.noSuchMethod, "myNamedFunction"));
testClassMock.getLogs(callsTo("myNamedFunction")).verify(happenedOnce);
});
}
class MyInvocation extends Invocation {
final String f;
MyInvocation(this.f);
bool get isGetter => false;
bool get isMethod => true;
bool get isSetter => false;
Symbol get memberName => new Symbol(f);
Map<Symbol, dynamic> get namedArguments => {};
List get positionalArguments => [];
}
testClassMock.myNamedFunction返回null,所以我直接调用noSuchMethod,而这需要一个Invocation。 调用是抽象的,所以我创建了一个实现。 MyFunc是一个包装函数的类。 MyFunc可以作为函数调用,因为它实现了调用方法。