Search code examples
c#testingpactcontract

Rewriting Pact contract test from JavaScript to C#


Apologies if this question is greaking the rules.

I have this js class:

src/get.js

const { get } = require('axios')

module.exports = function () {
    return get(`http://localhost:1234/token/1234`)
}

and also this test:

consumer.pact.js

const path = require("path")
const chai = require("chai")
const { Pact, Matchers } = require("@pact-foundation/pact")
const chaiAsPromised = require("chai-as-promised")
const expect = chai.expect
chai.use(chaiAsPromised)
const { string } = Matchers
const get = require('../src/get')

describe('Consumer Test', () => {
    const provider = new Pact({
        consumer: "React",
        provider: "token",
        port: 1234,
        log: path.resolve(process.cwd(), 'logs', 'pact.log'),
        dir: path.resolve(process.cwd(), 'pacts'),
        logLevel: "INFO"
    });

    before(() => provider.setup()
    .then(() => provider.addInteraction({
        state: "user token",
        uponReceiving: "GET user token",
        withRequest: {
            method: "GET",
            path: "/token/1234",
            headers: { Accept: "application/json, text/plain, */*" }
        },
        willRespondWith: {
            headers: { "Content-Type": "application/json" },
            status: 200,
            body: { "token": string("bearer") }
        }
    })))

    it('OK response', () => {
        get()
        .then((response) => {
            expect(response.statusText).to.be.equal('OK')
        })
    })

    after(() => provider.finalize())
})

I'm trying to write the equivalent in C# using the js code and the example here. I've done all except the GET and admittedly, what I've done so far might be way off. Here's what I have so far:

ConsumerTest.cs

//using NUnit.Framework;
using System.Collections.Generic;
using PactNet;
using PactNet.Mocks.MockHttpService;
using PactNet.Mocks.MockHttpService.Models;
using Xunit;

namespace PactTests.PactTests
{
  public class ConsumerTest : IClassFixture<ConsumerPact>
  {
    private IMockProviderService _mockProviderService;
    private string _mockProviderServiceBaseUri;

    public ConsumerTest(ConsumerPact data)
    {
      _mockProviderService = data.MockProviderService;
      _mockProviderService.ClearInteractions(); //NOTE: Clears any previously registered interactions before the test is run
      _mockProviderServiceBaseUri = data.MockProviderServiceBaseUri;
    }

    [Fact]
    public void OKResponse()
    {
      //Arrange
      _mockProviderService
        .Given("user token")
        .UponReceiving("GET user token")
        .With(new ProviderServiceRequest
        {
          Method = HttpVerb.Get,
          Path = "/token/1234",
          Headers = new Dictionary<string, object>
          {
            { "Accept", "application/json, text/plain, */*" }
          }
        })
        .WillRespondWith(new ProviderServiceResponse
        {
          Status = 200,
          Headers = new Dictionary<string, object>
          {
            { "Content-Type", "application/json" }
          },
          Body = new //NOTE: Note the case sensitivity here, the body will be serialised as per the casing defined
          {
            token = "bearer"
          }
        }); //NOTE: WillRespondWith call must come last as it will register the interaction

        var consumer = new SomethingApiClient(_mockProviderServiceBaseUri);

      //Act
      var result = consumer.GetSomething("tester");

      //Assert
      Assert.Equal("tester", result.id);

      _mockProviderService.VerifyInteractions(); //NOTE: Verifies that interactions registered on the mock provider are called at least once
    }
  }
}

ConsumerPact.cs

using PactNet;
using PactNet.Mocks.MockHttpService;
using System;

namespace PactTests.PactTests
{
  public class ConsumerPact : IDisposable
  {
    public IPactBuilder PactBuilder { get; private set; }
    public IMockProviderService MockProviderService { get; private set; }

    public int MockServerPort { get { return 1234; } }

    public string MockProviderServiceBaseUri { get { return String.Format("http://localhost:{0}", MockServerPort); } }

    public ConsumerPact()
    {
      // Pact configuration
      var pactConfig = new PactConfig
      {
        SpecificationVersion = "2.0.17",
        PactDir = @"Users/paulcarron/git/pact/pacts",
        LogDir = @"Users/paulcarron/git/pact/logs"
      };

      PactBuilder = new PactBuilder(pactConfig);

      PactBuilder
        .ServiceConsumer("React")
        .HasPactWith("token");

      MockProviderService = PactBuilder.MockService(MockServerPort);

    }

    public void Dispose()
    {
      PactBuilder.Build();
    }
  }
}

How do I do the GET?


Solution

  • What does

    var consumer = new SomethingApiClient(_mockProviderServiceBaseUri);
    ...
    var result = consumer.GetSomething("tester");
    

    do?

    That should be the API client code that performs the HTTP GET. Any HTTP client library should do the job, but importantly, it should be the API client you created to talk to your provider.

    See https://github.com/pact-foundation/pact-workshop-dotnet-core-v1/blob/master/CompletedSolution/Consumer/src/ConsumerApiClient.cs for an example API client that can replace the axios client from your JS code.