Skip to content

Support for RSpec's instance_double #197

Open
@delner

Description

@delner

As a developer using the JsonApiClient gem to implement a client, I'd like to test code that uses this client.

Take for example this client resource:

module MyApi
  class Widget < JsonApiClient::Resource
    property :serial_number, type: :string
  end
end

If I write an RSpec test that uses a double to stand in for a Widget object obtained from this API:

let(:widget) { double(MyApi::Widget) }
let(:serial_number) { "A12345" }
it do
  expect(widget).to receive(:serial_number).and_return(serial_number)
  expect(widget.serial_number).to eq(serial_number)
end

...the test passes. If instead I use an instance_double, because I want to verify I'm not mocking a property that doesn't exist:

let(:widget) { instance_double(MyApi::Widget) }
let(:serial_number) { "A12345" }
it do
  expect(widget).to receive(:serial_number).and_return(serial_number)
  expect(widget.serial_number).to eq(serial_number)
end

...then the same test fails, despite the Widget class having a serial_number property defined, which can be accessed like an instance method.

Failure/Error: expect(widget).to receive(:serial_number).and_return(serial_number)
       the MyApi::Widget class does not implement the instance method: serial_number

Looking at the JsonApiClient::Resource object, it appears the likely explanation comes from the use of method_missing to implement these properties. I would suggest either adding a respond_to? or other mechanism that allows instance_double to be used, or refactoring out the use of method_missing (the latter of which is probably a tall order.)

I think there's a lot of value in adding support for instance_double for developers who want to use JsonApiClient. As developers write more unit tests against clients that use JsonApiClient, they will rely heavily on mocks and stubs to prevent actual API calls from being made in their tests. And as highly encouraged by the RSpec folks, using instance_double over double will prevent those tests from errantly stubbing properties that don't exist on rapidly changing APIs, that otherwise could result in false negative tests.

Activity

chingor13

chingor13 commented on Oct 3, 2016

@chingor13
Collaborator

I'm sorry, I don't have much experience working with RSpec but would appreciate a PR if you think it's valuable. I also wouldn't be opposed to having a spec suite in parallel to the minitest one if this is something that's easy to break.

gaorlov

gaorlov commented on Mar 20, 2019

@gaorlov
Collaborator

Is this still an issue, @delner? Would you be willing to work with us to PR it into the gem?

delner

delner commented on Mar 20, 2019

@delner
Author

I haven't used this in some time, but I think method_missing in https://github.com/JsonApiClient/json_api_client/blob/master/lib/json_api_client/resource.rb#L551 as a means to access dynamic methods is a big part of this. If you query the Resource class with respond_to? it will respond false for any of these dynamic methods, which is clearly not the case. This is one of the reasons use of method_missing is generally not favored.

Although we'd have to verify it with RSpec, you might be able to remedy this by adding an override of respond_to? to Response that returns true if method_missing would've done something other than raise an error, false otherwise. Whether this will work will depend on how RSpec implements verifying doubles and the mechanism by which it verifies.

senid231

senid231 commented on Mar 21, 2019

@senid231
Member

@delner did you check it on master
I think instance_double should work now because we add getter and setter methods for defined properties

https://github.com/JsonApiClient/json_api_client/blob/master/lib/json_api_client/resource.rb#L259

delner

delner commented on Mar 21, 2019

@delner
Author

I have not; I don't think I've checked it since 2016, so there's a fair chance that things might behave a bit differently...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @chingor13@gaorlov@delner@senid231

        Issue actions

          Support for RSpec's `instance_double` · Issue #197 · JsonApiClient/json_api_client