How to check the request body with RSpec

73 views Asked by At

I have the following method

def post_it(data_hash)
  uri = URI.parse("https://example.com/api")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(uri.path)
  request.content_type = "application/json"
  request.body = data_hash.to_json

  response = http.request(request)

  return {code: response.code, body: JSON.parse(response.body)}
end

And I'd like to test with RSpec two things: 1- The request is made to the expected uri. 2- The request is made with the expected body.

The first point has been covered with

 it "is posted to the expected endpoint" do
   expect(Net::HTTP::Post).to receive(:new).with("/api")
   Gateway.new.post_it({id: 123})
 end

But I can't find a way (without mocking everything, which I'd like not to do) to test the second point. I have tried with VCR but it seems to me I can verify only the response.

Any ideas?

1

There are 1 answers

2
Christopher Tabula On

Try WebMock instead.

This gem supports mocking HTTP requests and asserting the request signature and response after the mock HTTP request was made using request callback.

Here's how we do it in your test:

describe Gateway
  let(:request_body) { { hello: 'world' } }
  
  before do
    # WebMock setup
    stub_request(:post, 'https://example.com/api')
      .to_return(body: { message: 'Success!' }.to_json)
  end

  context 'when client sends a request' do
    it 'has the correct request signature' do
      WebMock.after_request do |request| # with response: |req, resp|
        expect(request.uri.path).to eq('/api')
        expect(request.body).to eq(request_body.to_json)
      end

      described_class.new.post_it(request_body)
    end
  end
end