Search code examples
c#pactpact-net

C# PACT - Consumer Driven Contact testing - writing test for provider


I am trying to get my head about PACT and I am using the PACT-Net library to achieve this.

My tests on the Consumer are working fine but I am trying to setup the tests on the Provider. I am using the basic Web API project that loads when you use the Web API template within Visual Studio - which creates the Values API controller. I am just testing the Get IEumerable<string> method as an end to end test of the process. I am also following the example on the PACT-Net github site. Here is the test I have so far:

    [Fact]
    public void EnsureValuesReturnedFromApi()
    {
        var config = new PactVerifierConfig
        {
            Outputters = new List<IOutput>
            {
                new XUnitOutput(_output)
            }
        };

    using (WebApp.Start<TestStartup>(serviceUri))
    {
        var pactVerifier = new PactVerifier(config);
        pactVerifier.ProviderState($"{serviceUri}/provider-states")
            .ServiceProvider("Values API", serviceUri)
            .HonoursPactWith("Consumer")
            .PactUri("http://localhost:8080/pacts/provider/Values%20API/consumer/Consumer/latest")
            .Verify();
    }
}

When ever I run the unit test I get the following error:

Reading pact at http://localhost:8080/pacts/provider/Values%20API/consumer/Consumer/latest

Verifying a pact between Consumer and Values API
  Given When I want the values
    Getting a list
      with GET /api/values
        returns a response which
          has status code 200 (FAILED - 1)
          has a matching body (FAILED - 2)
          includes headers
            "Accept" with value "application/json" (FAILED - 3)
            "Content-Type" with value "application/json" (FAILED - 4)

Failures:

  1) Verifying a pact between Consumer and Values API Given When I want the values Getting a list with GET /api/values returns a response which has status code 200
     Failure/Error: set_up_provider_state interaction.provider_state, options[:consumer]

     Pact::ProviderVerifier::SetUpProviderStateError:
       Error setting up provider state 'When I want the values' for consumer 'Consumer' at http://localhost:9222/provider-states. response status=500 response body=

  2) Verifying a pact between Consumer and Values API Given When I want the values Getting a list with GET /api/values returns a response which has a matching body
     Failure/Error: set_up_provider_state interaction.provider_state, options[:consumer]

     Pact::ProviderVerifier::SetUpProviderStateError:
       Error setting up provider state 'When I want the values' for consumer 'Consumer' at http://localhost:9222/provider-states. response status=500 response body=

  3) Verifying a pact between Consumer and Values API Given When I want the values Getting a list with GET /api/values returns a response which includes headers "Accept" with value "application/json"
     Failure/Error: set_up_provider_state interaction.provider_state, options[:consumer]

     Pact::ProviderVerifier::SetUpProviderStateError:
       Error setting up provider state 'When I want the values' for consumer 'Consumer' at http://localhost:9222/provider-states. response status=500 response body=

  4) Verifying a pact between Consumer and Values API Given When I want the values Getting a list with GET /api/values returns a response which includes headers "Content-Type" with value "application/json"
     Failure/Error: set_up_provider_state interaction.provider_state, options[:consumer]

     Pact::ProviderVerifier::SetUpProviderStateError:
       Error setting up provider state 'When I want the values' for consumer 'Consumer' at http://localhost:9222/provider-states. response status=500 response body=

1 interaction, 1 failure

Failed interactions:

* Getting a list given When I want the values

I guess my question is, do I need to actually test the HTTP calls to /api/values or am I missing something else?

Thanks


Solution

  • So after speaking to a colleague and getting a hint, it was down to the Startup class. I hadn't realised it effectively starts the web application so

    public class TestStartup
    {
        public void Configuration(IAppBuilder app)
        {
            var startup = new Startup();
            app.Use<ProviderStateMiddleware>(); 
            startup.Configuration(app);
        }
    }
    

    calls the startup class within the application:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var httpConfig = new HttpConfiguration();
            httpConfig.MapHttpAttributeRoutes();
    
            httpConfig.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    
            var appXmlType = httpConfig.Formatters.XmlFormatter.SupportedMediaTypes
                                       .FirstOrDefault(t => t.MediaType == "application/xml");
            httpConfig.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
    
            app.UseWebApi(httpConfig);
        }
    }
    

    and my unit test passed. Hope this helps someone.