如何模拟具有常量数组和匿名函数作为参数的函数
How to mock a function that has constant array and anonymous function as parameters
我有一个接口函数,它有一个常量数组和一个匿名函数作为参数:
TCodeword = array[0..7] of Char;
TIntFunc = reference to function: Integer;
IMyInterface = interface(IInvokable)
function DoSomething(const codeword: TCodeword; func: TIntFunc): Boolean;
end;
我想模拟那个接口来测试一个正在使用它的对象:
function IntFunc: Integer;
begin
Result := 5;
end;
procedure Test;
var
MyInterfaceMock: Mock<IMyInterface>;
MyInterface: IMyInterface;
begin
MyInterfaceMock := Mock<IMyInterface>.Create(TMockbehavior.Strict);
MyInterfaceMock.Setup.Returns(true).When.DoSomething(arg.IsAny<TCodeword>, arg.IsAny<TIntFunc>());
MyInterface := MyInterfaceMock;
MyInterface.DoSomething('12345678', IntFunc);
end;
当 运行 时,ENotSupportedException: 'Type is not supported: TCodeword' is raised when Setup.
有人可以解释为什么这是不受支持的类型吗?如何传递未指定的 TCodeword 以正确模拟该函数?
或者我尝试在设置中传递显式参数:
procedure Test;
var
MyInterfaceMock: Mock<IMyInterface>;
MyInterface: IMyInterface;
begin
MyInterfaceMock := Mock<IMyInterface>.Create(TMockbehavior.Strict);
MyInterfaceMock.Setup.Returns(true).When.DoSomething('12345678', IntFunc);
MyInterface := MyInterfaceMock;
MyInterface.DoSomething('12345678', IntFunc);
end;
这样它适用于常量数组但不适用于匿名函数。我得到一个 EMockException:'unexpected call of function DoSomething(const codeword: TCodeword; func: TIntFunc): Boolean with arguments: nil, (array)';
我怎样才能完成这项工作?我很高兴能得到任何帮助!
存在多个问题:
因为异常指出不支持 TCodeword
类型——那是因为不支持 typeKind tkArray
类型——我不记得确切原因是因为内部处理与 tkDynArray 非常相似。我会解决这个问题,并在完成后对该答案进行编辑。
当将常规函数传递给方法引用参数时,编译器构建必要的代码以将常规函数包装到方法引用中,并使用接口对象实现方法的接口引用(毕竟匿名方法只是接口)。然而,每次发生这种情况时它都会这样做,这意味着将 IntFunc
传递给 TIntFunc
参数的两行是两个不同的指针。这就是为什么在内部参数匹配器 returns False。如果你想避免这种情况,你需要将 IntFunc
放入 TIntFunc
类型的局部变量中并传递它。因为这样编译器只构建一次包装代码,在这两种情况下,局部变量的值都会传递给 DoSomething
调用。
更新:已在开发分支中修复
我有一个接口函数,它有一个常量数组和一个匿名函数作为参数:
TCodeword = array[0..7] of Char;
TIntFunc = reference to function: Integer;
IMyInterface = interface(IInvokable)
function DoSomething(const codeword: TCodeword; func: TIntFunc): Boolean;
end;
我想模拟那个接口来测试一个正在使用它的对象:
function IntFunc: Integer;
begin
Result := 5;
end;
procedure Test;
var
MyInterfaceMock: Mock<IMyInterface>;
MyInterface: IMyInterface;
begin
MyInterfaceMock := Mock<IMyInterface>.Create(TMockbehavior.Strict);
MyInterfaceMock.Setup.Returns(true).When.DoSomething(arg.IsAny<TCodeword>, arg.IsAny<TIntFunc>());
MyInterface := MyInterfaceMock;
MyInterface.DoSomething('12345678', IntFunc);
end;
当 运行 时,ENotSupportedException: 'Type is not supported: TCodeword' is raised when Setup. 有人可以解释为什么这是不受支持的类型吗?如何传递未指定的 TCodeword 以正确模拟该函数?
或者我尝试在设置中传递显式参数:
procedure Test;
var
MyInterfaceMock: Mock<IMyInterface>;
MyInterface: IMyInterface;
begin
MyInterfaceMock := Mock<IMyInterface>.Create(TMockbehavior.Strict);
MyInterfaceMock.Setup.Returns(true).When.DoSomething('12345678', IntFunc);
MyInterface := MyInterfaceMock;
MyInterface.DoSomething('12345678', IntFunc);
end;
这样它适用于常量数组但不适用于匿名函数。我得到一个 EMockException:'unexpected call of function DoSomething(const codeword: TCodeword; func: TIntFunc): Boolean with arguments: nil, (array)';
我怎样才能完成这项工作?我很高兴能得到任何帮助!
存在多个问题:
因为异常指出不支持
TCodeword
类型——那是因为不支持 typeKindtkArray
类型——我不记得确切原因是因为内部处理与 tkDynArray 非常相似。我会解决这个问题,并在完成后对该答案进行编辑。当将常规函数传递给方法引用参数时,编译器构建必要的代码以将常规函数包装到方法引用中,并使用接口对象实现方法的接口引用(毕竟匿名方法只是接口)。然而,每次发生这种情况时它都会这样做,这意味着将
IntFunc
传递给TIntFunc
参数的两行是两个不同的指针。这就是为什么在内部参数匹配器 returns False。如果你想避免这种情况,你需要将IntFunc
放入TIntFunc
类型的局部变量中并传递它。因为这样编译器只构建一次包装代码,在这两种情况下,局部变量的值都会传递给DoSomething
调用。
更新:已在开发分支中修复