delphimockingspring4d

Delphi Spring Mock of reference to function


I have an interface and I want to mock a function of this interface with an argument which is a reference to a function. See code exmple:

unit Main;

interface

procedure Execute;

implementation

uses
  Spring.Mocking;

type
  TRefFunc = reference to function: Boolean;

  IHelper = interface
  ['{7950E166-1C93-47E4-8575-6B2CCEE05304}']
  end;

  IIntfToMock = interface
  ['{8D85A1CD-51E6-4135-B0E9-3E732400BA25}']
    function DoSth(const AHelper: IHelper; const ARef: TRefFunc): Boolean;
  end;

procedure Execute;
var
  IntfMock : Mock<IIntfToMock>;
begin
  IntfMock := Mock<IIntfToMock>.Create();
  IntfMock.Setup.Returns(True).When.DoSth(Arg.IsAny<IHelper>, Arg.IsAny<TRefFunc>);
end;

end.

Unfortunately I receive a compile error:

[dcc32 Error] Main.pas(29): E2010 incompatible types: 'TRefFunc' and 'Spring.Mocking.Matching.TArg.IsAny<Main.TRefFunc>'

I understand why passing a callback as an argument to a mocked method is not a good idea if the method will be mocked. The best solution is to refactor the code and remove the callback argument from the method. But I was wondering if it is possible to pass an argument, which is a callback, via the Arg.IsAny<T> syntax?

Thanks and keep healthy


Solution

  • When passing something that is invokable to a function reference parameter the compiler tries to build a closure on it to then pass it to the parameter. This happens also for variables:

    var
      f: TRefFunc;
    begin
      f := Arg.IsAny<TRefFunc>; // boom, E2010
    

    This is one of the few cases where Delphi needs the () on a call to understand that you actually want to invoke the rhs and assign its result.