1

How can I mock an interface method call like procedure foo( var i_ : integer ). The tested method local variable passed as a var param, so the test must use Arg.IsAny (The test does not access it). The result value is not the same as the out value of the var param, because the tested method does some processing on it before gives back as a result. The commented When variations in the test does not compile. The current one compiles but results an undefined value (mock Executes does not call at all, because the var=pointer values don't match). How could I mock a method call with a var parameter?

unit Unit1;

interface

uses
    DUnitX.TestFramework
  , Spring.Mocking
  ;

type
  IMyInterface = interface ( IInvokable )
    ['{606BA1D8-EAEC-42CB-A774-911628FD2E6C}']
    procedure foo( var x_ : integer );
  end;

  TMyClass = class
    private
      fMyInterface : IMyInterface;
    public
      constructor Create( myInterface_ : IMyInterface );
      function bar : integer;
  end;

  [TestFixture]
  TMyClassUnitTest = class
    public
      [Test]
      procedure bar;
  end;

implementation

constructor TMyClass.Create( myInterface_ : IMyInterface );
begin
  inherited Create;
  fMyInterface := myInterface_;
end;

function TMyClass.bar : integer;
var
  i : integer;
begin
  fMyInterface.foo( i );
  result := i + 1;
end;

procedure TMyClassUnitTest.bar;
var
  myInterfaceMock : Mock<IMyInterface>;
  myClass : TMyClass;
  i : integer;

  procedure prepareMyInterfaceFooCall( fooVarValue_ : integer );
  var
    ii : integer;
  begin
    ii := 7;
    myInterfaceMock.Setup.Executes(

      function ( const args_ : TCallInfo ) : TValue
      begin
        args_[0] := TValue.From<integer>( fooVarValue_ );
      end

    //).When.foo( Arg.IsAny<integer> );
    //).When.foo( integer( Arg.IsAny<integer> ) );
    ).When.foo( ii );
  end;

begin
  prepareMyInterfaceFooCall( 5 );
  myClass := TMyClass.Create( myInterfaceMock );
  try
    i := myClass.bar;
  finally
    FreeAndNIL( myClass );
  end;
  Assert.AreEqual( 6, i );
end;

end.
SOLID Developper
  • 672
  • 4
  • 12

1 Answers1

1

1.2.2 cannot do this but 2.0 can do (currently develop branch)

Here is the relevant change to your code:

procedure prepareMyInterfaceFooCall(expectedValue: Integer);
begin
  myInterfaceMock.Setup.Executes
  // put the wildcard matcher because your code passes a non initialized variable
  // a matcher on the When() always has priority over any individual parameter matching
  .When(Args.Any)
  // use the Arg.Ref syntax specifying the return value
  .foo(Arg.Ref<Integer>(expectedValue).Return);
end;
Stefan Glienke
  • 20,860
  • 2
  • 48
  • 102
  • Thanks for the hopeful answer. Approximately when does this version get accessible for downloading? As I can see nowadays just version 1.2.4 is downloadable. – SOLID Developper Jan 05 '22 at 10:49
  • I suggest using git to easily fetch any new commits quickly but there is also the branches tab in the download section which lets you download any branch you want – Stefan Glienke Jan 05 '22 at 14:54