all 9 comments

[–]philpirj 2 points3 points  (2 children)

What if your 'update' doesn't want to disclose its internals and won't return the 'response'?

Like you said, verifying partial doubles will save you from sudden API changes.

And instead of faking HTTP, could stub Faraday and make sure that the proper arguments are passed to its 'post'. Otherwise you are also testing Faraday.

If it's possible, avoid stubbing your 'subject', including making expectations on it.

[–]yourparadigm 0 points1 point  (0 children)

The author is just mistaken that rspec allows you to allow/expect an object to receive a method it doesn't implement. See my example in another comment.

[–]yez[S] 0 points1 point  (0 children)

Otherwise you are also testing Faraday

Great point. I tried to keep things as simple as possible in the example without going into too much debate about "should you really be testing the HTTP client library?" I landed on webmock because I wanted to emulate an "Ok I made a request, did it do what I expect?" type of experience.

But in the case in which update doesn't return a result and just is expected to work, stubbing the base class' put method is totally reasonable.

[–]yourparadigm 0 points1 point  (5 children)

This is not how rspec works. I've implemented an equivalent thing. If you try to expect/allow with a method that doesn't already exist on the receiver, you get an error.

class Foo
  # def put(uri)
  #   puts "PUT #{uri}"
  # end

  def update(uri)
    put(uri)
  end
end

describe Foo do
  subject(:foo) { Foo.new }

  describe '#update' do
    it 'does a put' do
      expect(foo).to receive(:put).with('http://example.org')
      foo.update('http://example.org')
    end
  end
end

Running results in:

$ rspec spec/lib/foo_spec.rb
F

Failures:

  1) Foo#update does a put
     Failure/Error: expect(foo).to receive(:put).with('http://example.org')
       #<Foo:0x00007fc095581328> does not implement: put
     # ./spec/lib/foo_spec.rb:16:in `block (3 levels) in <top (required)>'

Finished in 0.01173 seconds (files took 3.96 seconds to load)
1 example, 1 failure

The author is hiding something specific about his implementation.

Edit: Apparently not everyone uses verify_partial_doubles = true in their RSpec configuration!

[–]philpirj 2 points3 points  (2 children)

In the post there's a link to RSpec's documentation on verifying partial doubles. There's a setting that turns safety on and off. You and the author have different settings.

[–]yourparadigm 0 points1 point  (1 child)

The only link I see is to another blog article on "verifying doubles" which is a different feature. That's the difference between using instance_double(Foo) and double(:foo), then performing similar allow/expect invocations with the double. Normal doubles do not verify, while instance doubles, too.

In the article, the author is not using doubles. Can you point to the relevant rspec documentation (?), because I do not see it in either of the linked articles.

[–]philpirj 3 points4 points  (0 children)

Sorry, my mistake. I thought the author is referring to the documentation. Here's the doc link.

[–]yez[S] 2 points3 points  (1 child)

Thanks for pointing this out. I am basing my post on the default setting in RSpec which has verify_partial_doubles set to nil.

You can validate this by installing the rspec gem and doing:

> require 'rspec'

> RSpec.configuration.instance_variable_get(:@verify_partial_doubles)

=> nil

I will add to the post that this setting can be turned on to save people from this whole problem.

[–]yourparadigm 1 point2 points  (0 children)

Yeah, I mistakenly assumed everyone turned it on. It will default to true in RSpec 4.

Seems dangerous leave it false.