Search code examples
delphimockingdelphi-xe3spring4d

How can you Mock an Interface with Spring's DI Container without registering the Class Type?


I am trying to decouple existing code to be able to unit test it. I have introduced interfaces to remove the dependency on UI objects.The problem is that the Spring container's RegisterComponent < T > call requires a TComponentType parameter, so I cannot call RegisterComponent< IMyProgressBar > I have to call RegisterType < TMyProgressBar >.Implements < IMyProgressBar > which means I have to use the unit containing the progressbar class definition in DUnit which defeats the purpose of using the DIContainer in concert with the ServiceLocater to ask for a progressbar whenever I need one.

I don't want to have to create mock classes and implement the interfaces manually. Is there a way to use Delphi.Mocks to automatically mock an interface without specifying the implementing class?


Solution

  • You apparently do not use the latest version of Spring4D as this feature has been implemented last november (see the update in https://stackoverflow.com/a/11315141/587106)

    Currently there is no auto mocking of the container but I like the idea and will look into implementing something that makes this easier (possibly by improving the container extension).

    At the moment a test case method would look like this (using DSharp mocks syntax):

    procedure TMyTestCase.TestSomething;
    var
      progressBarMock: Mock<IProgressBar>;
      sut: TTestComponent;
    begin
      container.RegisterType<TTestComponent>;
      container.RegisterType<IProgressBar>.DelegateTo(
        function: IProgressBar
        begin
          Result := progressBarMock;
        end);
      container.Build;
    
      // mock setup
    
      sut := container.Resolve<TTestComponent>;
    
      // perform test
    end;
    

    Anyway I highly suggest writing unit tests without the use of a DI container.

    If your SUT has many dependencies making the use of the container appealing that is often a sign of violating certain design principles.