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.
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;