Noah Clark
Noah Clark

Reputation: 8131

How do I stub a method call followed by hash look up?

I have the following:

request.env['HTTP_REFERER']

and want to stub the request.env only when it is followed by the hash look up.

Any thoughts on how to do this?

Upvotes: 1

Views: 338

Answers (2)

tyamagu2
tyamagu2

Reputation: 969

I assume you want to stub #[] method of request.env. One way to do so is to define a singleton method in request.env using define_singleton_method and override the original #[] method.

[19] pry(main)> env = { a: 1 } # or whatever object of a class that has #[]
=> {:a=>1}
[20] pry(main)> env[:a]
=> 1
[21] pry(main)> env.size
=> 2
[22] pry(main)> env.define_singleton_method(:[]) { |key| key.upcase }
=> :[]
[23] pry(main)> env[:a]
=> :A
[24] pry(main)> env.size
=> 2
[25] pry(main)> env.define_singleton_method(:[]) { |key| key == 'HTTP_REFERER' ? 'http://example.com' : super(key) }
=> :[]
[26] pry(main)> env[:a]
=> 1
[27] pry(main)> env['HTTP_REFERER']
=> "http://example.com"

Upvotes: 2

nTraum
nTraum

Reputation: 1426

RSpec.describe Hash do
  subject { described_class.new(foo: :bar) }

  it "returns the value via #[]" do
    expect(subject).to receive("[]").with(:foo)
    subject[:foo]
  end
end

In Ruby, hash[:foo] is just syntactic sugar. It's identical to calling the method [] with the argument :foo on the hash:

hash = { foo: :bar }
#=> {:foo=>:bar}
hash.public_send("[]", :foo)
#=> :bar

Upvotes: 1

Related Questions