[英]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.