TMyClass
contains two references. A reference to an IList<integer>
and a reference to IMyInterface
. The mocking of IList<integer>
is not necessary. The framework probably well tested, well predictable behavior, so I could see it as a Data object. But IMyInterface
is an untested service, so I should mock it in a unit test.
I want to check for memory leaks so I want to test the modifications of the RefCount-s of the references after the subject destroyed.
The 'RefCount' of the IList<integer>
changes in the right way. But I can't say the same for the mocked IMyInterface
(in my solution). How could I test that the references does not cause memory leaks? Or a test like this is an integration test and should I test it always with real instances?
unit Unit1;
interface
uses
DUnitX.TestFramework
, Spring.Collections
, Spring.Mocking
;
type
IMyInterface = interface ( IInvokable )
['{76B13784-6CCF-4A87-882C-E624F003B082}']
procedure foo;
end;
TMyClass = class
private
fList : IList<integer>;
fMyInterface : IMyInterface;
public
constructor Create( list_ : IList<integer>; myInterface_ : IMyInterface );
end;
[TestFixture]
TMyClassTest = class
protected
function getInterfaceRefCount( const interface_ : IInterface ) : integer;
public
[Test]
procedure listRefCountTest;
[Test]
procedure myInterfaceRefCountTest;
end;
implementation
uses
System.SysUtils
;
constructor TMyClass.Create( list_ : IList<integer>; myInterface_ : IMyInterface );
begin
inherited Create;
fList := list_;
fMyInterface := myInterface_;
end;
function TMyClassTest.getInterfaceRefCount( const interface_ : IInterface ) : integer;
begin
result := ( interface_ as TInterfacedObject ).RefCount;
end;
procedure TMyClassTest.listRefCountTest;
var
list : IList<integer>;
myInterfaceMock : Mock<IMyInterface>;
myClass : TMyClass;
listRefCount : integer;
begin
list := TCollections.CreateList<integer>;
myClass := TMyClass.Create( list, myInterfaceMock );
try
listRefCount := getInterfaceRefCount( list );
finally
FreeAndNIL( myClass );
end;
Assert.AreEqual( listRefCount-1, getInterfaceRefCount( list ) );
end;
procedure TMyClassTest.myInterfaceRefCountTest;
var
list : IList<integer>;
myInterfaceMock : Mock<IMyInterface>;
myClass : TMyClass;
myInterfaceRefCount : integer;
begin
list := TCollections.CreateList<integer>;
myClass := TMyClass.Create( list, myInterfaceMock );
try
myInterfaceRefCount := getInterfaceRefCount( myInterfaceMock.Instance );
finally
FreeAndNIL( myClass );
end;
Assert.AreEqual( myInterfaceRefCount-1, getInterfaceRefCount( myInterfaceMock.Instance ) );
end;
initialization
TDUnitX.RegisterTestFixture(TMyClassTest);
end.
Memoryleak checking does not need to be done explicitly - I suggest using https://github.com/shadow-cs/delphi-leakcheck for that - it can seemlessly integrated with either DUnit or DUnitX and automatically provides you with all the information you need when a leak occurs (opposed to only telling you "there was a leak of x bytes" which out of the box DUnit does by simply comparing allocated bytes before and after running the test)