Skip to content

InteractionContents does not support raw strings neither integer values (and certainly more types) #402

@aurelien-reeves-scalingo

Description

When trying to migrate existing interactions from Pact v1 to Pact v2, I faced undefined method 'each_pair' for an instance of String errors

I traced it back to the InteractionContents class, where the serialize method seems to lack support for some types.

Here are two examples, based on own pact providers tests providers/pact-ruby-v2-test-app/http_client_spec.rb:

When expected response is plain text:

    context 'with successful interaction' do
      let(:interaction) do
        super()
          .given('pet exists', pet_id: pet_id)
          .upon_receiving('getting a pet')
          .with_request(method: :get, path: "/pets/#{pet_id}")
          .will_respond_with(status: 200, body: "plain text")
      end

      it 'executes the pact test without errors' do
        interaction.execute do
          expect(make_request).to be_success
        end
      end
Failures:

  1) PactProviders::Test::HttpClient with GET /pets/:id with successful interaction executes the pact test without errors
     Failure/Error: init_hash(contents_hash, format).each_pair { |k, v| self[k] = v }
     
     NoMethodError:
       undefined method 'each_pair' for an instance of String
     # ./lib/pact/consumer/interaction_contents.rb:20:in 'Pact::Consumer::InteractionContents#initialize'
     # ./lib/pact/consumer/interaction_contents.rb:12:in 'Class#new'
     # ./lib/pact/consumer/interaction_contents.rb:12:in 'Pact::Consumer::InteractionContents.basic'
     # ./lib/pact/consumer/http_interaction_builder.rb:100:in 'Pact::Consumer::HttpInteractionBuilder#will_respond_with'
     # ./spec/pact/providers/pact-ruby-v2-test-app/http_client_spec.rb:31:in 'block (4 levels) in <top (required)>'
     # ./spec/pact/providers/pact-ruby-v2-test-app/http_client_spec.rb:35:in 'block (4 levels) in <top (required)>'

When expected response contains an Integer:

    context 'with successful interaction' do
      let(:interaction) do
        super()
          .given('pet exists', pet_id: pet_id)
          .upon_receiving('getting a pet')
          .with_request(method: :get, path: "/pets/#{pet_id}")
          .will_respond_with(status: 200, body: {some_array: [42]})
      end

      it 'executes the pact test without errors' do
        interaction.execute do
          expect(make_request).to be_success
        end
      end
Failures:

  1) PactProviders::Test::HttpClient with GET /pets/:id with successful interaction executes the pact test without errors
     Failure/Error:
               hash.each_pair do |key, value|
                 next serialize(value, format) if value.is_a?(Hash)
                 next hash[key] = value.map { |v| serialize(v, format) } if value.is_a?(Array)
       
                 if value.is_a?(Pact::Matchers::Base)
                   hash[key] = value.as_basic if format == :basic
                   hash[key] = value.as_plugin if format == :plugin
                 end
                 if value.is_a?(Pact::Generators::Base)
                   hash[key] = value.as_basic if format == :basic
     
     NoMethodError:
       undefined method 'each_pair' for an instance of Integer
     # ./lib/pact/consumer/interaction_contents.rb:38:in 'Pact::Consumer::InteractionContents#serialize'
     # ./lib/pact/consumer/interaction_contents.rb:40:in 'block (2 levels) in Pact::Consumer::InteractionContents#serialize'
     # ./lib/pact/consumer/interaction_contents.rb:40:in 'Array#map'
     # ./lib/pact/consumer/interaction_contents.rb:40:in 'block in Pact::Consumer::InteractionContents#serialize'
     # ./lib/pact/consumer/interaction_contents.rb:38:in 'Hash#each_pair'
     # ./lib/pact/consumer/interaction_contents.rb:38:in 'Pact::Consumer::InteractionContents#serialize'
     # ./lib/pact/consumer/interaction_contents.rb:56:in 'Pact::Consumer::InteractionContents#init_hash'
     # ./lib/pact/consumer/interaction_contents.rb:20:in 'Pact::Consumer::InteractionContents#initialize'
     # ./lib/pact/consumer/interaction_contents.rb:12:in 'Class#new'
     # ./lib/pact/consumer/interaction_contents.rb:12:in 'Pact::Consumer::InteractionContents.basic'
     # ./lib/pact/consumer/http_interaction_builder.rb:100:in 'Pact::Consumer::HttpInteractionBuilder#will_respond_with'
     # ./spec/pact/providers/pact-ruby-v2-test-app/http_client_spec.rb:31:in 'block (4 levels) in <top (required)>'
     # ./spec/pact/providers/pact-ruby-v2-test-app/http_client_spec.rb:35:in 'block (4 levels) in <top (required)>'

Indeed, by reading the code of InteractionContents, it appears that a lot of use-cases are missing beside hash and Strings and arrays which contains only hash and strings

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions