首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >spring4d注销接口类型(spring4d、dunitx、delphi-模拟)

spring4d注销接口类型(spring4d、dunitx、delphi-模拟)
EN

Stack Overflow用户
提问于 2015-01-13 10:33:58
回答 1查看 535关注 0票数 5

我正在编写我的第一个单元-使用spring4d,dunitx和delphi-模拟测试。(spring4d 1.1-12.09.2014版)

在我的测试应用程序中,我在测试类(Sut)下向我的系统注入一个接口:

代码语言:javascript
复制
IMyInterface = interface [{yes, a GUID here}]
  function GetSomething1: TSomething1;
  function GetSomething2: TSomething2;
end;

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

现在,当我使用带有模拟的单元测试时,我使用了以下(非常简单的)代码:

代码语言:javascript
复制
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(找到的重复服务名称:GlobalContainer.Build)

是否有可能取消注册aIntfMock,这样我就可以为每个其他测试例程注册一个新的?

编辑以便解决方案如下:

代码语言:javascript
复制
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;

谢谢你的快速答复..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-13 11:31:17

简短答覆:否

很长的答案:容器不支持注销任何注册类型的可能性。这是因为注销任何内容都会对其他类型和创建的实例(特别是单例)造成级联效应。

我总是建议不要使用GlobalContainer,而是创建自己的TContainer实例。然后,您可以抛出实例,在下一个测试中使用一个新的实例。

您可以查看我们的单元测试如何完成(在TContainerTestCase中有Spring.Tests.Container.pas类)

除了容器之外,您还应该避免在测试中使用单例。每个单元测试都应该隔离。一旦涉及到全局状态,您可能会有副作用。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27920058

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档