簡體   English   中英

spring4d取消注冊接口類型(spring4d,dunitx,delphi-mocks)

[英]spring4d unregister interface type (spring4d, dunitx, delphi-mocks)

我正在使用spring4d,dunitx和delphi-mocks編寫我的第一個單元測試之一。 (spring4d版本1.1 - 12.09.2014)

在我的測試應用程序中,我自動將一個接口連接到我的系統測試類(sut):

IMyInterface = interface [{yes, a GUID here}]
  function GetSomething1: TSomething1;
  function GetSomething2: TSomething2;
end;

TMyClass = class
private
    [Inject]
    FMyInterface: IMyInterface;
    // ...
end;

現在,當我使用模擬的單元測試時,我使用以下(非常簡單的)代碼:

TMyTest = class
private
    [Test]
    procedure Test1;

    [Test]
    procedure Test2;
    // ...
end;

procedure TMyTest.Test1;
var
    aSut: TMyClass;
    aIntfMock: TMock<IMyInterface>;
    aSomething1: TSomething1;
begin
    // Arrange
    GlobalContainer.RegisterType<TMyClass>;

    aIntfMock := TMock<IMyInterface>.Create;
    try
        GlobalContainer.RegisterType<IMyInterface>.DelegateTo(
            function: IMyInterface
            begin
                Result := aIntfMock;
            end)
            .AsDefault;

        GlobalContainer.Build;

        aSomething1 := TSomething1.Create;
        try
            aIntfMock.Setup.WillReturn(TValue.From<TSomething1>(aSomething1)).When.GetSomething1;

            aSut := GlobalContainer.Resolve<TMyClass>;
            try
                // Act
                aSut.DoSomething;
            finally
                 FreeAndNil(aSut);
            end;

            // Assert
            // ...
        finally
            FreeAndNil(aSomething1);
        end;
    finally
        aIntfMock.Free; 
    end;
end;

procedure TMyTest.Test2;
var
    aSut: TMyClass;
    aIntfMock: TMock<IMyInterface>;
    aSomething2: TSomething2;
begin
    // Arrange
    GlobalContainer.RegisterType<TMyClass>;

    aIntfMock := TMock<IMyInterface>.Create;
    try
        GlobalContainer.RegisterType<IMyInterface>.DelegateTo(
            function: IMyInterface
            begin
                Result := aIntfMock;
            end)
            .AsDefault;


        GlobalContainer.Build;   // <---- ERegistrationException here

        aSomething2 := TSomething1.Create;
        try
            aIntfMock.Setup.WillReturn(TValue.From<TSomething2>(aSomething2)).When.GetSomething2;

            aSut := GlobalContainer.Resolve<TMyClass>;
            try
                // Act
                aSut.DoSomething;
            finally
                 FreeAndNil(aSut);
            end;

            // Assert
            // ...
        finally
            FreeAndNil(aSomething2);
        end;
    finally
        aIntfMock.Free; 
    end;
end;

第一個測試方法(Test1)運行良好......但是在第二個測試方法(Test2)中,在GlobalContainer.Build的行中,spring4d引發了一個異常:ERegistrationException('找到重復的服務名:IMyInterface_u.IMyInterface@IMyInterface_u.IMyInterface' )。

是否有可能取消注冊aIntfMock,所以我可以為每個其他測試例程注冊一個新的?

[編輯]所以解決方案是:

TMyTest = class
private
    FTestContainer: TContainer;
    FIntfMock: TMock<IMyInterface>;
    FSut: TMyClass;

    [Setup]
    procedure Setup;
    [TearDown]
    procedure TearDown;
    [Test]
    procedure Test1;

    [Test]
    procedure Test2;
    // ...
end;

//---------------------

procedure TMyTest.Setup;
begin
    FTestContainer := TContainer.Create;
    FTestContainer.RegisterType<TMyClass>;

    FIntfMock := TMock<IMyInterface>.Create;    

    FTestContainer.RegisterType<IMyInterface>.DelegateTo(
        function: IMyInterface
        begin
            Result := FIntfMock;
        end)
        .AsDefault;

    FTestContainer.Build;

    FSut := FTestContainer.Resolve<TMyClass>;
end;

procedure TMyTest.TearDown;
begin
    FreeAndNil(FSut);
    FIntfMock.Free;
    FreeAndNil(FTestContainer);
end;

procedure TMyTest.Test1;
var
    aSomething1: TSomething1;
begin
    // Arrange

    aSomething1 := TSomething1.Create;
    try
        aIntfMock.Setup.WillReturn(TValue.From<TSomething1>(aSomething1)).When.GetSomething1;

        // Act
        FSut.DoSomething;

        // Assert
        // ...

    finally
        FreeAndNil(aSomething1);
    end;
end;

procedure TMyTest.Test2;
begin
    // ...
end;

謝謝你的快速回答......

簡答:不

答案很長:沒有支持容器取消注冊任何已注冊類型的可能性。 這是因為取消注冊任何內容都可能導致其他類型以及創建的實例(尤其是單例)上的級聯效果。

我總是建議不要使用GlobalContainer,而是創建自己的TContainer實例。 然后你可以拋棄實例並使用一個新實例進行下一次測試。

您可以查看我們的單元測試如何完成(Spring.Tests.Container.pas中有TContainerTestCase類)

除了容器,你應該避免在測試中使用單身。 每個單元測試都應該是隔離的。 一旦涉及全球狀態,您可能會產生副作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM