Work in Progress
Diese Seite ist aktuell im Review! Die Seite wurde noch nicht qualitätsgesichert und kann Fehler enthalten.
Die verlinkten Seiten sind ggf. nur für Schleupen-Mitarbeiter sichtbar.

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\">&lt;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\"&gt;&lt;ViewId&gt;ce86ad17-7556-4dd1-a7ef-e3b7534747ee&lt;/ViewId&gt;&lt;ElementId&gt;0015e9fe-ff25-4c81-934c-aca7fcd73c8a&lt;/ElementId&gt;&lt;CreatorSid&gt;S-1-5-21-2370327874-3712188522-606064691-203197&lt;/CreatorSid&gt;&lt;CreatorExternalId&gt;S-1-5-21-2370327874-3712188522-606064691-203197&lt;/CreatorExternalId&gt;&lt;SystemUsageId&gt;00000000-0000-0000-0000-000000000001&lt;/SystemUsageId&gt;&lt;Extensions /&gt;&lt;/SessionToken&gt;</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

Benutze Muster

Cookie Consent mit Real Cookie Banner