Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Producer tests failing with non-beta package #530

Open
bertracoon opened this issue Dec 17, 2024 · 4 comments
Open

Producer tests failing with non-beta package #530

bertracoon opened this issue Dec 17, 2024 · 4 comments
Labels
bug Indicates an unexpected problem or unintended behavior triage This issue is yet to be triaged by a maintainer

Comments

@bertracoon
Copy link

bertracoon commented Dec 17, 2024

Previous issues
I have searched issues in this and other pact-foundation repos, as well as searching online and attempting to sign up for slack.

Version information:

  • OS: MacOS M1 ARM (also reproduced on Windows x64 and Azure Devops ubuntu agents)
  • PactNet Version: 5.0.0
  • .Net Version: 8.0.403
  • Pact Broker Version (if applicable): Consumers using same .NET/PactNet version. Pacts in pactflow.io

Describe the bug
Producer tests which previously worked using 5.0.0-beta.2 fail to run when updated to 5.0.0. Tests fail with

Request Failed - builder error for url (message://localhost:49152/pact-messages)

Steps To Reproduce
Update PactNet from 5.0.0-beta.2 to 5.0.0
Running tests using several test runners and xunit.

Example test

using PactNet;
using PactNet.Infrastructure.Outputters;
using PactNet.Output.Xunit;
using PactNet.Verifier;
using System.Text.Json;
using System.Text.Json.Serialization;
using Domain.Events;
using Xunit.Abstractions;

namespace ContractTests;

public class CustomerProductAccessRequestsProviderTests
{
    private static readonly JsonSerializerOptions Options =
    new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = true,
        Converters = { new JsonStringEnumConverter() },
    };

    private readonly PactVerifierConfig _config;

    public CustomerProductAccessRequestsProviderTests(ITestOutputHelper output)
    {
        _config = new PactVerifierConfig
        {
            Outputters = new List<IOutput>
        {
            new XunitOutput(output),
            new ConsoleOutput()
        },

            LogLevel = PactLogLevel.Debug,
        };
    }

    [Fact]
    public void ProviderForConsumerMembershipCreditHold()
    {
        using var pactVerifier = new PactVerifier("CustomerProductAccessBlockRequested", _config);

        pactVerifier
            .WithMessages(scenarios =>
            {
                var message = new CustomerProductAccessBlockRequested (12345,"customerAccountCode");
                scenarios.Add("A CustomerProductAccessBlockRequested message", builder => builder.WithContent(() => message, Options));

            }, Options)
            .WithPactBrokerSource(new Uri(PactBrokerConfig.PactBrokerUrl), options =>
            {
                options.TokenAuthentication(PactBrokerConfig.PactBrokerToken);

                options.PublishResults(PactBrokerConfig.ProviderVersion, publishOptions =>
                {
                    publishOptions.ProviderBranch(PactBrokerConfig.ProviderBranch);
                    publishOptions.ProviderTags(PactBrokerConfig.ProviderTags.Split(','));
                });
            })
            .Verify();
    }
}

Expected behavior
Tests should run and pass or fail based on contract using latest non-beta package.

Log Output

PactNet.Exceptions.PactVerificationFailedException: Pact verification failed

PactNet.Exceptions.PactVerificationFailedException
Pact verification failed
at PactNet.Verifier.InteropVerifierProvider.Execute()
at PactNet.Verifier.PactVerifierSource.Verify()
at CustomerProductAccessRequestsProviderTests.ProviderForConsumerMembershipCreditHold() in /Users/user/Source/test/pact/Tests/CustomerProductAccessRequestsProviderTests.cs:line 43
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Starting messaging provider at http://localhost:49152/pact-messages/
Messaging provider successfully started
Starting verification...
Pact verification failed

Verifier Output

The pact at https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/consumer/Membership.CreditHold.CustomerProductAccessBlockRequested/pact-version/7eec1c139f9cff34f415ef40e4cfa4c1add732d4 is being verified because the pact content belongs to the consumer version matching the following criterion:
* latest version of Membership.CreditHold.CustomerProductAccessBlockRequested from the main branch 'main' (0.0.2)

Verifying a pact between Membership.CreditHold.CustomerProductAccessBlockRequested and CustomerProductAccessBlockRequested

A CustomerProductAccessBlockRequested message (2s 759ms loading, 274ms verification)
Given A plan's credit status needs to be set to Suspended
Request Failed - builder error for url (message://localhost:49152/pact-messages)

Failures:

  1. Verifying a pact between Membership.CreditHold.CustomerProductAccessBlockRequested and CustomerProductAccessBlockRequested Given A plan's credit status needs to be set to Suspended - A CustomerProductAccessBlockRequested message - builder error for url (message://localhost:49152/pact-messages)

There were 1 pact failures

Verifier Logs

2024-12-16T16:27:03.876145Z INFO ThreadId(01) pact_verifier::pact_broker: Fetching path '' from pact broker
2024-12-16T16:27:03.876229Z DEBUG ThreadId(01) pact_verifier::pact_broker: Final broker URL: https://mycompany.pactflow.io/
2024-12-16T16:27:03.876361Z DEBUG ThreadId(01) reqwest::connect: starting new connection: https://mycompany.pactflow.io/
2024-12-16T16:27:03.924305Z DEBUG ThreadId(01) hyper_util::client::legacy::connect::http: connecting to 18.172.88.111:443
2024-12-16T16:27:03.947033Z DEBUG ThreadId(01) hyper_util::client::legacy::connect::http: connected to 18.172.88.111:443
2024-12-16T16:27:04.709953Z DEBUG ThreadId(01) pact_verifier::pact_broker: Link URL is templated
2024-12-16T16:27:04.709963Z DEBUG ThreadId(01) pact_verifier::pact_broker: templated URL = https://mycompany.pactflow.io/pacts/provider/{provider}/for-verification
2024-12-16T16:27:04.710970Z DEBUG ThreadId(01) pact_verifier::pact_broker: final URL = https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/for-verification
2024-12-16T16:27:04.710994Z INFO ThreadId(01) pact_verifier::pact_broker: Fetching path '/pacts/provider/CustomerProductAccessBlockRequested/for-verification' from pact broker
2024-12-16T16:27:04.710999Z DEBUG ThreadId(01) pact_verifier::pact_broker: Final broker URL: https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/for-verification
2024-12-16T16:27:04.711016Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:05.384786Z DEBUG ThreadId(01) pact_verifier::pact_broker: templated URL = https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/for-verification
2024-12-16T16:27:05.385872Z DEBUG ThreadId(01) pact_verifier::pact_broker: final URL = https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/for-verification
2024-12-16T16:27:05.385902Z DEBUG ThreadId(01) pact_verifier::pact_broker: Sending JSON to https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/for-verification using POST: {"includePendingStatus":false,"consumerVersionSelectors":[]}
2024-12-16T16:27:05.385945Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:05.751041Z INFO ThreadId(01) pact_verifier::pact_broker: Fetching path '/pacts/provider/CustomerProductAccessBlockRequested/consumer/Membership.CreditHold.CustomerProductAccessBlockRequested/pact-version/7eec1c139f9cff34f415ef40e4cfa4c1add732d4/metadata/c1tdW2N2XT0xMTY3' from pact broker
2024-12-16T16:27:05.751052Z DEBUG ThreadId(01) pact_verifier::pact_broker: Final broker URL: https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/consumer/Membership.CreditHold.CustomerProductAccessBlockRequested/pact-version/7eec1c139f9cff34f415ef40e4cfa4c1add732d4/metadata/c1tdW2N2XT0xMTY3
2024-12-16T16:27:05.751068Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:06.651546Z DEBUG ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier: Executing provider states
2024-12-16T16:27:06.651601Z INFO ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier: Running setup provider state change handler 'A plan's credit status needs to be set to Suspended' for 'A CustomerProductAccessBlockRequested message'
2024-12-16T16:27:06.651607Z WARN ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier::callback_executors: State Change ignored as there is no state change URL provided for interaction ec13b619980eaa70fbc255c9f74a456a6e47efcd
2024-12-16T16:27:06.651610Z DEBUG ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier: State Change: "ProviderState { name: "A plan's credit status needs to be set to Suspended", params: {} }" -> Ok({})
2024-12-16T16:27:06.651623Z INFO ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier: Running provider verification for 'A CustomerProductAccessBlockRequested message'
2024-12-16T16:27:06.651633Z DEBUG ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier: Verifying an asynchronous message (single shot)
2024-12-16T16:27:06.651667Z INFO ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier::provider_client: Sending request to provider at message://localhost:49152/pact-messages/
2024-12-16T16:27:06.651670Z DEBUG ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier::provider_client: Provider details = ProviderInfo { name: "CustomerProductAccessBlockRequested", protocol: "message", host: "localhost", port: Some(49152), path: "/pact-messages/", transports: [ProviderTransport { transport: "message", port: Some(49152), path: Some("/pact-messages/"), scheme: Some("message") }] }
2024-12-16T16:27:06.651687Z INFO ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier::provider_client: Sending request HTTP Request ( method: POST, path: /, query: None, headers: Some({"Content-Type": ["application/json"]}), body: Present(145 bytes, application/json) )
2024-12-16T16:27:06.651693Z DEBUG ThreadId(01) verify_interaction{interaction="A CustomerProductAccessBlockRequested message"}: pact_verifier::provider_client: body:
{"description":"A CustomerProductAccessBlockRequested message","providerStates":[{"name":"A plan's credit status needs to be set to Suspended"}]}
2024-12-16T16:27:06.651786Z INFO ThreadId(01) pact_verifier: Publishing verification results back to the Pact Broker
2024-12-16T16:27:06.651788Z DEBUG ThreadId(01) pact_verifier: Publishing a failure result to PactBroker(https://mycompany.pactflow.io/, provider_name='CustomerProductAccessBlockRequested')
2024-12-16T16:27:06.855401Z INFO ThreadId(01) pact_verifier::pact_broker: Fetching path '/pacticipants/CustomerProductAccessBlockRequested' from pact broker
2024-12-16T16:27:06.855425Z DEBUG ThreadId(01) pact_verifier::pact_broker: Final broker URL: https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested
2024-12-16T16:27:06.855453Z DEBUG ThreadId(01) reqwest::connect: starting new connection: https://mycompany.pactflow.io/
2024-12-16T16:27:06.857548Z DEBUG ThreadId(01) hyper_util::client::legacy::connect::http: connecting to 18.172.88.111:443
2024-12-16T16:27:06.882562Z DEBUG ThreadId(01) hyper_util::client::legacy::connect::http: connected to 18.172.88.111:443
2024-12-16T16:27:07.409114Z DEBUG ThreadId(01) pact_verifier::pact_broker: templated URL = https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/branches/{branch}/versions/{version}
2024-12-16T16:27:07.410207Z DEBUG ThreadId(01) pact_verifier::pact_broker: final URL = https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/branches/dev/versions/1.0.0
2024-12-16T16:27:07.410223Z DEBUG ThreadId(01) pact_verifier::pact_broker: Sending JSON to https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/branches/dev/versions/1.0.0 using PUT: {}
2024-12-16T16:27:07.410258Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:07.795506Z DEBUG ThreadId(01) pact_verifier::pact_broker: Pushed branch dev for provider version 1.0.0
2024-12-16T16:27:07.795747Z INFO ThreadId(01) pact_verifier::pact_broker: Fetching path '/pacticipants/CustomerProductAccessBlockRequested' from pact broker
2024-12-16T16:27:07.795760Z DEBUG ThreadId(01) pact_verifier::pact_broker: Final broker URL: https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested
2024-12-16T16:27:07.795838Z DEBUG ThreadId(01) reqwest::connect: starting new connection: https://mycompany.pactflow.io/
2024-12-16T16:27:07.796122Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:08.450504Z DEBUG ThreadId(01) pact_verifier::pact_broker: templated URL = https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/versions/{version}/tags/{tag}
2024-12-16T16:27:08.451396Z DEBUG ThreadId(01) pact_verifier::pact_broker: final URL = https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/versions/1.0.0/tags/latest
2024-12-16T16:27:08.451409Z DEBUG ThreadId(01) pact_verifier::pact_broker: Sending JSON to https://mycompany.pactflow.io/pacticipants/CustomerProductAccessBlockRequested/versions/1.0.0/tags/latest using PUT: {}
2024-12-16T16:27:08.451440Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:08.821906Z DEBUG ThreadId(01) pact_verifier::pact_broker: Pushed tag latest for provider version 1.0.0
2024-12-16T16:27:08.821953Z DEBUG ThreadId(01) pact_verifier::pact_broker: Sending JSON to https://mycompany.pactflow.io/pacts/provider/CustomerProductAccessBlockRequested/consumer/Membership.CreditHold.CustomerProductAccessBlockRequested/pact-version/7eec1c139f9cff34f415ef40e4cfa4c1add732d4/metadata/c1tdW2N2XT0xMTY3/verification-results using POST: {"providerApplicationVersion":"1.0.0","success":false,"testResults":[{"exceptions":[{"message":"builder error for url (message://localhost:49152/pact-messages)"}],"interactionDescription":"A CustomerProductAccessBlockRequested message","interactionId":"ec13b619980eaa70fbc255c9f74a456a6e47efcd","success":false}],"verifiedBy":{"clientLanguage":{"name":"pact-net","testFramework":"pact_ffi","version":"5.0.0.0"},"implementation":"Pact-Rust","version":"1.2.5"}}
2024-12-16T16:27:08.821990Z DEBUG ThreadId(01) hyper_util::client::legacy::pool: reuse idle connection for ("https", mycompany.pactflow.io)
2024-12-16T16:27:09.547844Z INFO ThreadId(01) pact_verifier: Results published to Pact Broker
2024-12-16T16:27:09.547938Z WARN ThreadId(01) pact_matching::metrics:
--snip

Additional context
Comparing this to the run which works successfully using beta.2 it appears to be attempting to connect to message://localhost:49152/pact-messages rather than http://localhost:49152/pact-messages/. This appears to be where it fails.

pact_verifier::provider_client: Sending request to provider at message://localhost:49152/pact-messages/
vs
pact_verifier::provider_client: Sending request to provider at http://localhost:49152/pact-messages/

Looking at the changes between beta.2 and 5.0.0 the main thing is the underlying ffi package, it does look like something may have changed with the ProviderInfo class in there.

5.0.0-beta.2...5.0.0

FFI_VERSION="0.4.16" > FFI_VERSION="0.4.23"

If this is the case I'm surprised we are the only people having this issue unless most are doing API verification.

@bertracoon bertracoon added bug Indicates an unexpected problem or unintended behavior triage This issue is yet to be triaged by a maintainer labels Dec 17, 2024
@zerdush
Copy link

zerdush commented Dec 17, 2024

We are having the same issue. The below sample works for beta2 but not in 5.0.0
Test Consumer-Test Provider.json
`using System.Text.Json;
using PactNet;
using PactNet.Verifier;
using Xunit.Abstractions;

namespace Tests.Pact;

public class SimpleEventProviderPactTest : IDisposable
{
private readonly PactVerifier _verifier;

public SimpleEventProviderPactTest(ITestOutputHelper testOutputHelper)
{
    _verifier = new PactVerifier("Test Provider", new PactVerifierConfig()
    {
        LogLevel = PactLogLevel.Debug,
        Outputters =
        [
            new XunitOutput(testOutputHelper)
        ]
    });
}

[Fact]
public void EnsureEventApiHonoursPactWithConsumer()
{
    var defaultSettings = new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };
    
    _verifier
        .WithMessages(scenarios =>
        {
            // register the responses to each interaction
            // the descriptions must match those in the pact file(s)
            scenarios
                .Add("Simple event published", builder =>
                {
                    builder.WithContent(() => 
                        
                            new
                            {
                                Id = "event-001"
                            }
                        );
                });
        }, defaultSettings)
        .WithFileSource(new FileInfo("./pacts/Test Consumer-Test Provider.json"))
      
        .Verify();
}

public void Dispose()
{
    // make sure you dispose the verifier to stop the internal messaging server
    GC.SuppressFinalize(this);
    _verifier.Dispose();
}

}`

@adamrodger
Copy link
Contributor

Thanks for the really detailed bug report 🤘

@adamrodger
Copy link
Contributor

@mefellows I've not looked into this yet but just tagging for visibility because it looks like it could be an FFI issue

@YOU54F
Copy link
Member

YOU54F commented Dec 19, 2024

i saw the same,

https://github.com/pact-foundation/pact-workshop-message/blob/ef0a00509fab5c5e9775ac515d38ee32582f86eb/provider-dotnet-kafka/tests/ProviderApiTests.cs#L66

you need to set the http url for the message proxy server that pact-net spins up.

you shouldn’t need to in the consumer facing dsl but this is a workaround

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior triage This issue is yet to be triaged by a maintainer
Projects
None yet
Development

No branches or pull requests

4 participants