gpt4 book ai didi

delphi - spring4d 注销接口(interface)类型(spring4d、dunitx、delphi-mocks)

转载 作者:行者123 更新时间:2023-12-03 15:11:07 25 4
gpt4 key购买 nike

我正在使用 spring4d、dunitx 和 delphi-mocks 编写我的第一个单元测试。(spring4d 版本 1.1 - 2014 年 9 月 12 日)

在我的测试应用程序中,我将接口(interface)自动连接到测试类 (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 类)

除了容器之外,无论如何您都应该避免在测试中使用单例。每个单元测试都应该是隔离的。一旦涉及全局状态,您可能会产生副作用。

关于delphi - spring4d 注销接口(interface)类型(spring4d、dunitx、delphi-mocks),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27920058/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com