如何模拟具有常量数组和匿名函数作为参数的函数

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)';

我怎样才能完成这项工作?我很高兴能得到任何帮助!

存在多个问题:

  1. 因为异常指出不支持 TCodeword 类型——那是因为不支持 typeKind tkArray 类型——我不记得确切原因是因为内部处理与 tkDynArray 非常相似。我会解决这个问题,并在完成后对该答案进行编辑。

  2. 当将常规函数传递给方法引用参数时,编译器构建必要的代码以将常规函数包装到方法引用中,并使用接口对象实现方法的接口引用(毕竟匿名方法只是接口)。然而,每次发生这种情况时它都会这样做,这意味着将 IntFunc 传递给 TIntFunc 参数的两行是两个不同的指针。这就是为什么在内部参数匹配器 returns False。如果你想避免这种情况,你需要将 IntFunc 放入 TIntFunc 类型的局部变量中并传递它。因为这样编译器只构建一次包装代码,在这两种情况下,局部变量的值都会传递给 DoSomething 调用。

更新:已在开发分支中修复