ContractTest für Services
ContractTests helfen bei der Vermeidung von Inkompatibilitäten in synchronen Service-Calls ohne vollintegrative End2End-Tests.
Design
Mittels des Fakeservers werden Service-Calls in sog. Mapping Dateien mitgeschnitten.
Das ContractTestFixture
(Nuget Paket Schleupen.CS.PI.Framework.Contract.Testing.Net) stellt Methoden bereit um die, in den Mapping Dateien enthaltenen, Request-/Response-Tupel zu deserialisieren. Die Request kann dann an eine, in einem Component-Test gehostete, Service-Instanz gesendet werden. Im Anschluss wird die empfangene Response mir der erwarteten Response verglichen.
Implementierung
Die Datei Mapping_Schleupen.AS.MT.BIB.Buecher.BuchQueryService_3.1_QueryTitel.json wurde mit Hilfe des Fakeserver erzeugt und enthält ein Request-/Response-Tupel zum einem Aufruf von Schleupen.AS.MT.BIB.Buecher.BuchQueryService_3.1/QueryTitel (gekürzte Darstellung):
{ "Guid": "f22ae9c9-6378-4003-a4d1-6a76e13d9865", "UpdatedAt": "2024-02-08T09:53:33.2387817Z", "Title": "Proxy Mapping for POST /Schleupen/Service Bus/Broker/BrokerService.svc", "Description": "Proxy Mapping for POST /Schleupen/Service Bus/Broker/BrokerService.svc", "Priority": -2000000, "Request": { "Methods": [ "POST" ], "Body": { "Matcher": { "Name": "ExactMatcher", "Pattern": "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Header><h:SessionToken xmlns:h=\"urn://Schleupen.CS.PI.SB.Broker_3.2\"><SessionToken xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"Schleupen.CS.PI.SB_3.2\"><ViewId>ce86ad17-7556-4dd1-a7ef-e3b7534747ee</ViewId><ElementId>0015e9fe-ff25-4c81-934c-aca7fcd73c8a</ElementId><CreatorSid>S-1-5-21-2370327874-3712188522-606064691-203197</CreatorSid><CreatorExternalId>S-1-5-21-2370327874-3712188522-606064691-203197</CreatorExternalId><SystemUsageId>00000000-0000-0000-0000-000000000001</SystemUsageId><Extensions /></SessionToken></h:SessionToken><h:IdempotencyKey i:nil=\"true\" xmlns:h=\"urn://Schleupen.CS.PI.SB.Idempotency_3.0\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"/></s:Header><s:Body><QueryTitelRequest xmlns=\"urn://Schleupen.AS.MT.BIB.Buecher.BuchQueryService_3.1\"><MaxResults>0</MaxResults><TitelCriteria xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Titel>DDD</Titel></TitelCriteria></QueryTitelRequest></s:Body></s:Envelope>", "IgnoreCase": true } } }, "Response": { "StatusCode": 200, "Body": "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><QueryTitelResponse xmlns=\"urn://Schleupen.AS.MT.BIB.Buecher.BuchQueryService_3.1\"><BuchInfo2Liste xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><BuchInfo2Contract><Titel>DDD</Titel></BuchInfo2Contract></BuchInfo2Liste></QueryTitelResponse></s:Body></s:Envelope>", } }
Die Datei wird in Visual Studio neben den Test abgelegt und die Eigenschaft In Ausgabeverzeichnis kopieren auf Immer kopieren gesetzt:
Im Folgenden wird die Implementierung des eigentlichen Tests gezeigt:
[Test] public void VerifyQueryTitel_WithCannedRequest_ReturnsExpectedResponse() { using (ITransactionScope transactionScope = fixture.CreateTransactionScope()) { fixture.CreatePersistedBuchWithTitelSample("DDD"); transactionScope.Complete(); } FileInfo file = new("Queries\\Buecher\\QueryService\\V3_1\\\\Mapping_Schleupen.AS.MT.BIB.Buecher.BuchQueryService_3.1_QueryTitel.json"); ContractTestFixture contractTestFixture = new(file); QueryTitelRequest request = contractTestFixture.GetCannedRequest<QueryTitelRequest>(); QueryTitelResponse expectedResponse = contractTestFixture.GetCannedResponse<QueryTitelResponse>(); QueryTitelResponse actualResponse = null; fixture.WithOpenedServiceHost(client => actualResponse = client.QueryTitel(request)); actualResponse.Should().BeEquivalentTo(expectedResponse, options => options.Excluding(x => x.Name == nameof(BuchInfo2Contract.ExtensionData))); }
Stärken und Schwächen
Stärken
- Geringerer Implementierungsaufwand im Vergleich zu E2E-Tests
- Ermöglicht Consumer-driven Contract Tests (die Mapping-Dateien werden von den Verwendern des Services (Consumer) bereit gestellt)
- Kann in Component Tests verwendet werden
Schwächen
- Die Erzeugung der Mapping-Dateien erfordert eine passende Umgebung
- Bei Consumer-driven Contract Tests müssen sich Consumer und Provider zusätzlich über nötige Testdaten abstimmen