Hi All, I am using 2 services with JS and PHP lang...
# general
m
Hi All, I am using 2 services with JS and PHP languages While doing the provider test getting the following error
Copy code
2024-04-02T12:13:50.251575Z ERROR ThreadId(09) pact_verifier: Failed to load pact - Failed to load pact from '<http://localhost:9292>'
I am able to see the consumer contract is available in the fetched path. Any help here please
y
This is usually a mismatch in consumer version selectors, but with very limited information it is hard to tell. Can you provide more context?
m
The Consumer Test Code
Copy code
<?php

//namespace MessageConsumer;

require_once __DIR__ . '/../../CommandMessageConsumer.php';

use Exception;
use GuzzleHttp\Psr7\Uri;
use PhpPact\Consumer\MessageBuilder;
use PhpPact\Standalone\PactConfigInterface;
use PhpPact\Standalone\PactMessage\PactMessageConfig;
use PhpPact\Standalone\ProviderVerifier\Model\VerifierConfig;
use PHPUnit\Framework\TestCase;
use stdClass;

/**
 * Class ExampleMessageConsumerTest
 */
class ReplyMessageConsumerTest extends TestCase
{
    private static PactConfigInterface $config;

    public static function setUpBeforeClass(): void
    {
        parent::setUpBeforeClass();

        self::$config = (new PactMessageConfig())
                        ->setConsumer('PayoutService')
                        ->setProvider('LedgerService')
                        ->setPactDir('pacts/pcl/');
    }

    public static function tearDownAfterClass(): void
    {
        parent::tearDownAfterClass();
    }

    /**
     * @throws Exception
     */
    public function testProcessPayload()
    {   
        $builder    = new MessageBuilder(self::$config);

        $contents       = new stdClass();
        $contents->responseType = 'ACCEPTED';
            
        $body = new stdClass();
        $body->caller_source_id = 'ledger-processor';
        $body->instrument_type = 'CURRENCY';
        $body->last_update_at = '1663227601993';
        $body->transaction_id = 'payment-processor_2007';
        $body->value = 0.55;
        $body->currency = 'EUR';
        $body->status = 'REDEEMED';
        $body->user_id = 'usr_sai';
            
        $metadata = new stdClass();
        $metadata->last_update_at = '1663227601993';

        $body->metadata = $metadata;
           
        $contents->body = $body;


        //$metadata = ['queue'=>'test_queue', 'routing_key'=>'test_routing_key'];
        $metadata = [];

        $builder
            ->given('a transaction')
            ->expectsToReceive('a transaction message')
            ->withMetadata($metadata)
            ->withContent($contents);

        // established mechanism to this via callbacks
        $consumerMessage = new CommandMessageConsumer();
        $callback        = [$consumerMessage, 'ProcessPayload'];
        $builder->setCallback($callback);

        $hasException = false;

        try {
            $builder->verify();
        } catch (Exception $e) {
            $hasException = true;
        }

        $this->assertFalse($hasException, 'Expects verification to pass without exceptions being thrown');
    }
}
The Contract
Copy code
{
  "consumer": {
    "name": "PayoutService"
  },
  "provider": {
    "name": "LedgerService"
  },
  "messages": [
    {
      "description": "a transaction message",
      "metadata": {
        "contentType": "application/json"
      },
      "providerStates": [
        {
          "name": "a transaction"
        }
      ],
      "contents": {
        "responseType": "ACCEPTED",
        "body": {
          "caller_source_id": "ledger-processor",
          "instrument_type": "CURRENCY",
          "last_update_at": "1663227601993",
          "transaction_id": "payment-processor_2007",
          "value": 0.55,
          "currency": "EUR",
          "status": "REDEEMED",
          "user_id": "usr_sai",
          "metadata": {
            "last_update_at": "1663227601993"
          }
        }
      },
      "matchingRules": {}
    }
  ],
  "metadata": {
    "pactSpecification": {
      "version": "2.0.0"
    }
  }
}
The Provider Code
Copy code
const {ReplyHandler} = require('../ls-provider')

const {
    MessageProviderPact,
    providerWithMetadata,
  } = require('@pact-foundation/pact');

  describe('LedgerService provider tests', () => {
    const p = new MessageProviderPact({
      messageProviders: {
        'a transaction message': providerWithMetadata(() => ReplyHandler(), {
          queue: 'transactions',
        }),
      },
      provider: 'LedgerService',
      
      //providerVersion: versionFromGitTag(),
      pactBrokerUrl: '<http://localhost:9292>',
      publishVerificationResult: true,
      providerVersion: '1.0',
      consumerVersionSelectors: ['1.0'],
      //logLevel: "DEBUG",
      //verbose: true,
    });
  
    describe('send a reply event', () => {
      it('sends a valid reply', () => {
        return p.verify();
      });
    });
  });
pact/bin/pact-broker publish ./pacts/pcl --consumer-app-version 1.0 --broker-base-url ‘http://localhost:9292
y
your consumer version selectors are incorrect, its not an array of string values, its an array of json objects with the relevant selectors
m
The same code for another service is working properly
Copy code
const {createTransaction} = require('../cs-provider')

const {
    MessageProviderPact,
    providerWithMetadata,
  } = require('@pact-foundation/pact');

  describe('CommissionService provider tests', () => {
    const p = new MessageProviderPact({
      messageProviders: {
        'a transaction message': providerWithMetadata(() => createTransaction(), {
          queue: 'transactions',
        }),
      },
      provider: 'CommissionService',
      
      //providerVersion: versionFromGitTag(),
      pactBrokerUrl: '<http://localhost:9292>',
      publishVerificationResult: true,
      providerVersion: '1.0',
      consumerVersionSelectors: ['1.0']
    });
  
    describe('send a transaction event', () => {
      it('sends a valid transaction', () => {
        return p.verify();
      });
    });
  });
y
possibly because its the latest pact, it doesn’t change the fact that you are using
consumerVersionSelectors
incorrectly
m
Both are running on same pact version
m
Copy code
consumerVersionSelectors: [{
        latest: true,
      },],
Used this and still seeing the same error
My pact version is 11.0.2
y
• `latest`: true. Used in conjuction with the
tag
property. If a
tag
is specified, and
latest
is
true
, then the latest pact for each of the consumers with that tag will be returned. If a
tag
is specified and the latest flag is not set to
true
, all the pacts with the specified tag will be returned. (This might seem a bit weird, but it’s done this way to match the syntax used for the matrix query params. See https://docs.pact.io/selectors).
read the docs buddy
> pact/bin/pact-broker publish ./pacts/pcl --consumer-app-version 1.0 --broker-base-url ‘http://localhost:9292’ You should be publishing with a branch, if its the main branch it will be picked up the main branch selector > • `mainBranch`: if the key is specified, can only be set to
true
. Return the pacts for the configured
mainBranch
of each consumer. Use of this selector requires that the consumer has configured the
mainBranch
property, and has set a branch name when publishing the pacts. As of October 2021, this is not yet supported in all Pact client libraries. If your consumer is publishing on a branch other than main, you can pick it up via • webhooks, triggering a verification by url • including work in progress pacts, which will trigger on provider verifications, as well as the consumer version selectors If you are just wanting to pick up a specific consumer branch (which is unlikely, you can add that in via selector) You need to use tags, if you are using latest flag, in the consumer version selectors, as per the docs. pact-js should probably error if you pass in invalid consumerVersionSelectors, rather than defaulting to passing no version selectors
m
Hi Yousaf, Thanks for the suggestions. Tried all and still seeing the same issue. I suspect a consumer contract generated from PHP package verifying against a JS provider is coming up with issues it seems. The same implementation is properly working if both the applications are JS based
💡 1
y
ahh it may be that pact-php is serialising the message contract as pact spec 2.0.0, but messages were only introduced in v3 spec I would recommend using the pact-php v10 alpha, now on the master branch https://docs.pact.io/blog/2024/03/26/pact-open-source-update-mar-2024#php There is an upgrading guide, and examples for message based systems https://github.com/pact-foundation/pact-php/blob/master/UPGRADE-10.0.md It would mean the pacts generated would be from the same pact-core (built in rust) over the prior ruby implementation. You may be able to get away with updating the spec value, but it would want passing through a pact schema validator to confirm its valid to v3 spec, but I would suggest using the new pact-php impl should solve your woes and be a better path to follow (as the ruby based impl won’t really be serviced any longer)
m
Thanks Yousaf. Did the changes and fixed the issue