2024-03-28 23:57:59 +01:00
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Delphi MVC Framework
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2010-2024 Daniele Teti and the DMVCFramework Team
|
|
|
|
|
//
|
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
|
//
|
|
|
|
|
// The Initial Developer of the Original Code is Vivaticket S.p.A. https://www.vivaticket.com/
|
|
|
|
|
// The code has been fully donated to the DMVCFramework community without any charge nor rights.
|
|
|
|
|
//
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
//
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
|
|
unit InjectorTestU;
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
DUnitX.TestFramework, MVCFramework.Container,
|
|
|
|
|
MVCFramework.Serializer.JsonDataObjects;
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
|
|
|
|
|
[TestFixture]
|
|
|
|
|
TTestContainer = class
|
|
|
|
|
public
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestNotBuiltContainer;
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestUnknownService;
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestTransient;
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestSingleton;
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestSingletonPerRequest;
|
|
|
|
|
[Test]
|
|
|
|
|
procedure TestCascadeConstructorInjection;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IServiceA = interface
|
|
|
|
|
['{B6C5EAD8-9008-4200-BF33-E3DE5C8A2320}']
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
IServiceB = interface
|
|
|
|
|
['{8418244D-8AEC-4567-A21E-3F4ECD07E227}']
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
IServiceC = interface
|
|
|
|
|
['{A9E5FD77-87FD-4C9C-91BA-79556252DAAD}']
|
|
|
|
|
function GetServiceA: IServiceA;
|
|
|
|
|
function GetServiceB: IServiceB;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TServiceA = class(TInterfacedObject, IServiceA)
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TServiceB = class(TInterfacedObject, IServiceB)
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TServiceAB = class(TInterfacedObject, IServiceA, IServiceB)
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TServiceC = class(TInterfacedObject, IServiceC)
|
|
|
|
|
private
|
|
|
|
|
fServiceA: IServiceA;
|
|
|
|
|
fServiceB: IServiceB;
|
|
|
|
|
protected
|
|
|
|
|
function GetServiceA: IServiceA;
|
|
|
|
|
function GetServiceB: IServiceB;
|
|
|
|
|
public
|
|
|
|
|
constructor Create(ServiceA: IServiceA; ServiceB: IServiceB);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
System.Generics.Collections, MVCFramework.IntfObjectPool, System.SysUtils, System.Classes, SyncObjs,
|
|
|
|
|
MVCFramework.Serializer.Intf;
|
|
|
|
|
|
|
|
|
|
{ TTestContainer }
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestCascadeConstructorInjection;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer;
|
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA);
|
2024-04-17 09:57:22 +02:00
|
|
|
|
lCont.RegisterType(TServiceB, IServiceB, TRegistrationType.SingletonPerRequest);
|
2024-03-28 23:57:59 +01:00
|
|
|
|
lCont.RegisterType(TServiceC, IServiceC);
|
|
|
|
|
lCont.Build;
|
|
|
|
|
|
|
|
|
|
// 1<> "request"
|
|
|
|
|
var lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l0 := lResolver.Resolve(TypeInfo(IServiceC)) as IServiceC;
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceA);
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceB);
|
|
|
|
|
|
|
|
|
|
// resolve another "IServiceC" in the same request - ServiceB is rtSingletonPerRequest
|
|
|
|
|
var l01 := lResolver.Resolve(TypeInfo(IServiceC)) as IServiceC;
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceA);
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceB);
|
|
|
|
|
Assert.AreNotEqual(l0.GetServiceA, l01.GetServiceA);
|
|
|
|
|
Assert.AreEqual(l0.GetServiceB, l01.GetServiceB);
|
|
|
|
|
|
|
|
|
|
// 2<> "request"
|
|
|
|
|
lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l1 := lResolver.Resolve(TypeInfo(IServiceC)) as IServiceC;
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceA);
|
|
|
|
|
Assert.IsNotNull(l0.GetServiceB);
|
|
|
|
|
Assert.AreNotEqual(l0.GetServiceA, l1.GetServiceA);
|
|
|
|
|
Assert.AreNotEqual(l0.GetServiceB, l1.GetServiceB);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestNotBuiltContainer;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer;
|
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA);
|
|
|
|
|
var lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
Assert.WillRaise(
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
var l0 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
end, EMVCContainerError);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestSingleton;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer;
|
2024-04-17 09:57:22 +02:00
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA, TRegistrationType.Singleton);
|
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA, TRegistrationType.Singleton, 'Svc1');
|
2024-03-28 23:57:59 +01:00
|
|
|
|
lCont.Build;
|
|
|
|
|
|
|
|
|
|
// 1<> Request
|
|
|
|
|
var lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l0 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
var l1 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
Assert.AreEqual(l0, l1);
|
|
|
|
|
var l2 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
var l3 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
Assert.AreEqual(l2, l3);
|
|
|
|
|
|
|
|
|
|
// 2<> Request
|
|
|
|
|
lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l10 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
var l11 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
Assert.AreEqual(l10, l11);
|
|
|
|
|
Assert.AreEqual(l0, l10);
|
|
|
|
|
Assert.AreEqual(l1, l11);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestSingletonPerRequest;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer
|
2024-04-17 09:57:22 +02:00
|
|
|
|
.RegisterType(TServiceA, IServiceA, TRegistrationType.SingletonPerRequest)
|
|
|
|
|
.RegisterType(TServiceA, IServiceA, TRegistrationType.SingletonPerRequest, 'Svc1');
|
2024-03-28 23:57:59 +01:00
|
|
|
|
lCont.Build;
|
|
|
|
|
|
|
|
|
|
// 1<> "request"
|
|
|
|
|
var lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l0 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
var l1 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
Assert.AreEqual(l0, l1);
|
|
|
|
|
var l2 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
var l3 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
Assert.AreEqual(l2, l3);
|
|
|
|
|
|
|
|
|
|
// 2<> "request"
|
|
|
|
|
lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l00 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
var l10 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
Assert.AreEqual(l00, l10);
|
|
|
|
|
Assert.AreNotEqual(l0, l00);
|
|
|
|
|
Assert.AreNotEqual(l1, l10);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestTransient;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer;
|
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA);
|
2024-04-17 09:57:22 +02:00
|
|
|
|
lCont.RegisterType(TServiceA, IServiceA, TRegistrationType.Transient, 'Svc1');
|
2024-03-28 23:57:59 +01:00
|
|
|
|
lCont.Build;
|
|
|
|
|
var lResolver := NewServiceContainerResolver(lCont);
|
|
|
|
|
var l0 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
var l1 := lResolver.Resolve(TypeInfo(IServiceA));
|
|
|
|
|
Assert.AreNotEqual(l0, l1);
|
|
|
|
|
var l2 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
var l3 := lResolver.Resolve(TypeInfo(IServiceA), 'Svc1');
|
|
|
|
|
Assert.AreNotEqual(l2, l3);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TTestContainer.TestUnknownService;
|
|
|
|
|
begin
|
|
|
|
|
var lCont := NewMVCServiceContainer;
|
|
|
|
|
Assert.WillRaise(
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
lCont.RegisterType(TServiceA, IServiceB);
|
|
|
|
|
end, EMVCContainerErrorUnknownService);
|
|
|
|
|
|
|
|
|
|
Assert.WillRaise(
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
lCont.RegisterType(TMVCJsonDataObjectsSerializer, IServiceB);
|
|
|
|
|
end, EMVCContainerErrorUnknownService);
|
|
|
|
|
|
|
|
|
|
Assert.WillRaise(
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
lCont.RegisterType(TServiceA, IMVCSerializer);
|
|
|
|
|
end, EMVCContainerErrorUnknownService);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
{ TServiceC }
|
|
|
|
|
|
|
|
|
|
constructor TServiceC.Create(ServiceA: IServiceA; ServiceB: IServiceB);
|
|
|
|
|
begin
|
|
|
|
|
inherited Create;
|
|
|
|
|
fServiceA := ServiceA;
|
|
|
|
|
fServiceB := ServiceB;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TServiceC.GetServiceA: IServiceA;
|
|
|
|
|
begin
|
|
|
|
|
Result := fServiceA;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TServiceC.GetServiceB: IServiceB;
|
|
|
|
|
begin
|
|
|
|
|
Result := fServiceB;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
initialization
|
|
|
|
|
|
|
|
|
|
TDUnitX.RegisterTestFixture(TTestContainer);
|
|
|
|
|
|
|
|
|
|
end.
|