I'm a newbie with Dependency Injection containers, and I am trying to get my head around using them in conjunction with Mocking.
Lets say I have a controller and a list (the model):
IBlahList = interface
property Items[AIndex: integer]: IBlah read GetItem;
end;
IController = interface
property List: IBlahList read GetList;
end;
The implementation of IController would look something like (note, it's in the implementaion
section:
implementation
TController = class (TInterfacedObject, IController)
private
FList: IBlahList;
function GetList: IBlahList;
public
constructor Create(const AList: IBlahList);
end;
And then, of course, I would register this class (as well as one for IBlahList) with the GlobalContainer
:
GlobalContainer.RegisterType<TController>.Implements<IController>;
I place the TController in the implementation
section, as suggested by various sources (well, Nick Hodges anyway!), so that we cannot reference the TController class directly.
Now, just say I want to test my implementation of ICollection in a unit test:
procedure TestSomething
var
LMockList: TMock<IBlahList>;
LController: IController;
begin
LMockList := TMock<IBlahList>.Create;
// Oops, I can't do this, I can't access TController
LController := TController.Create(LMockList);
end;
So, my question is, should I move the TController class into my interface
section so I can test it, or is there some other way to pass the mock IBlahList to the controller that I have yet to find?
If you have the concrete class in the implementation section, then you could expose a factory function (i.e. have it in the interface section) that creates an IController with the required parameters.
It makes absolutely no sense to have an implementation that can not be instantiated, IMO.
interface
...
function CreateController(AList: IBlahList): IController;
implementation
function CreateController(AList: IBlahList): IController;
begin
Result := TController.Create(AList);
end;