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

Missing obvious way to clear stubs #1041

Closed
viraptor opened this issue Sep 30, 2019 · 3 comments · Fixed by #1045
Closed

Missing obvious way to clear stubs #1041

viraptor opened this issue Sep 30, 2019 · 3 comments · Fixed by #1045

Comments

@viraptor
Copy link
Contributor

viraptor commented Sep 30, 2019

Basic Info

  • Faraday Version: 0.15.4
  • Ruby Version: 2.5

Issue description

I'm trying to stub responses in two tests, but I can't find an obvious way to clear the previous stubs from the test adapter, since the same instance is reused.

Steps to reproduce

RSpec.describe "something" do
  let(:test_faraday) do
    Faraday::Connection.new do |conn|
      conn.use Faraday::Adapter::Test do |stub|
        stub.post '/foo' do |env|
          response
        end
      end
    end
  end
  context "success" do
    let(:response) { [200, {}, 'foo'] }
    it "succeeds" do
      expect(Faraday::Connection).to receive(:new).and_return(test_faraday)
      Faraday.post("/foo")
    end
  end
  context "failure" do
    let(:response) { [500, {}, 'foo'] }
    it "fails" do
      expect(Faraday::Connection).to receive(:new).and_return(test_faraday)
      Faraday.post("/foo")
    end
  end
end

In this situation I get either both requests responding 200, or both responding 500. The adapter configuration runs only once and I can't find an obvious way to clear it from the middleware cache.

@BobbyMcWho
Copy link
Contributor

BobbyMcWho commented Sep 30, 2019

You could try

after(:each) do 
 test_faraday.adapter.stubs = nil
end

Edit: Thought stubs was a hash but it's an object

@viraptor
Copy link
Contributor Author

viraptor commented Oct 1, 2019

ArgumentError:
  wrong number of arguments (given 0, expected 1+)

@BobbyMcWho
Copy link
Contributor

BobbyMcWho commented Oct 1, 2019

Side note:
You're gonna wanna update your code to .adapter(adapter) from .use(adapter) before using 1.0 or 0.16.0

Sorry for not going deeper into this the first time, my suggestion was off the cuff and I'm sorry it didn't actually work 😞

The issue you're running into is that when you call Faraday.post, it sets a default connection which is cached for further Faraday.method calls. if you'd prefer to keep the general structure of your tests, you can set that default adapter to nil between tests:

require 'rspec'
require 'faraday'
RSpec.describe "something" do
  let(:test_faraday) do
    Faraday::Connection.new do |conn|
      conn.adapter Faraday::Adapter::Test do |stub|
        stub.post '/foo' do |env|
          response
        end
      end
    end
  end

  after(:each) do
    Faraday.default_connection = nil
  end

  context "success" do
    let(:response) { [200, {}, 'foo'] }
    it "succeeds" do
      # I changed the expects to allows, you should add an assertion below
      allow(Faraday::Connection).to receive(:new).and_return(test_faraday)

      response = Faraday.post("/foo")

      expect(response.status).to eq(200)
    end
  end

  context "failure" do
    let(:response) { [500, {}, 'foo'] }
    it "fails" do
      allow(Faraday::Connection).to receive(:new).and_return(test_faraday)

      response = Faraday.post("/foo")

      expect(response.status).to eq(500)
    end
  end
end

I would recommend wrapping the stub in a clearly named method so that when future folks are reading your tests it's very clear what is going on during setup, exercise, and assert:

require 'rspec'
require 'faraday'
RSpec.describe "something" do
  context "success" do
    it "succeeds" do
      stub_faraday_response(:post, '/foo', [200, {}, 'foo'])

      response = Faraday.post("/foo")

      expect(response.status).to eq(200)
      expect(response.body).to eq('foo')
    end
  end

  context "failure" do
    it "fails" do
      stub_faraday_response(:post, '/foo', [500, {}, 'foo'])

      response = Faraday.post("/foo")

      expect(response.status).to eq(500)
      expect(response.body).to eq('foo')
    end
  end
end

def stub_faraday_response(http_method, url, response)
  Faraday.default_connection = Faraday::Connection.new do |conn|
    conn.adapter Faraday::Adapter::Test do |stub|
      stub.send(http_method, url) do
        response
      end
    end
  end
end

Edit: removed the first example because it didn't actually work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants