Rspec 3 - Stub a Class Method

rspec 3 - stub a class method

You should do

allow(MyMod::Utils).to receive(:find_x).and_return({something: 'testing'})

Check out the doco Method stubs.

How to mock class method in RSpec expect syntax?

Here's what you want to do (no need for double):

allow(Facebook)
.to receive(:profile)
.with("token")
.and_return({"name" => "Hello", "id" => "14314141", "email" => "hello@me.com"})

stubbing a class method inside a method in rspec to return true

Ensure the syntaxing of mocking the return value is correct:

 allow(SiteLicenseService).to 
receive(:get_package_for_site_license).and_return(true)

In Ruby, classes are written in TitleCase and methods are written in snake_case. The method to be received should be a :symbol.

RSpec - mock a private class method call inside a request spec?

You're mocking on the class, which is how you mock you "static" class-level methods. For example, if your method was def self.foo and you called it via MyClass.foo, then allow(MyClass) is the way to go.

Your method is not a class-level method, it's an instance method. You invoke it by first creating an instead of MyClass and then calling the method on that instance. You need to use allow_any_instance_of to mock the method for all future instances of the class:

allow_any_instance_of(MyClass).to receive(....)

How to stub a class method using rspec/rspec-mocks

For your workflow, I think it's going to work better to use a class_double than than to stub the Hashes class directly. allow(Hashes) is always going to require that the Hashes constant is defined. It's simply how Ruby works and RSpec can't do anything about that. With a class double, you can instead do this:

class_double("Hashes", :calculate_hash => canned_return_value).as_stubbed_const

# or

hashes = class_double("Hashes").as_stubbed_const
allow(hashes).to receive(:calculate_hash) do |file|
# look up what to return
end

class_double("Hashes") provides you with a test double that, when the Hashes constant is defined, will verify the mocked and stubbed methods against the Hashes class definition, but when it is not defined, will act just like a normal double that allows anything to be mocked or stubbed on it. The as_stubbed_const bit tells rspec-mocks to stub the Hashes constant for the duration of the example so that any references to Hashes get your class double rather than the real Hashes class, even if the Hashes class has never been defined.

Stub a 'nested' class method that is called by a wrapper method (RSpec Mocks)

You may want to use RSpec's allow(...) to stub the intermediate method. This is also useful for testing logic flow or for mocking third-party services in tests.

For example:

expected_response = 'This is a different string'
allow(Thing).to receive(:method_three).and_return(expected_response)

Then expect(Thing.method_one('Hi')).to eq(expected_response) should pass.

See https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/method-stubs for more information on stubbing methods.

Is there a way to stub all methods of a particular class in RSpec 3?

Yes, stub_everything is deprecated.

Yes, you can use as_null_object to stub everything in your test like this:

let(:push_service) { double(PushService).as_null_object }

When you use as_null_object, your object will respond to any method that is not implemented. It will also allow you to use explicit stubs and explicit expectations.

See Null object doubles documentation for more information.

How do I stub a class method with a class_double in RSpec?

class_double doesn't actually replace the constant. You can call as_stubbed_const to replace the original

class_double("Project").as_stubbed_const

This is the just a convenience wrapper around stub_const

How to stub class instantiated inside tested class in rspec

Reaching for DI is always a good idea (https://stackoverflow.com/a/51401376/299774) but there are sometimes reasons you can't so it, so here's another way to stub it without changing the "production" code.

1. expect_any_instance_of

it 'uploads to google cloud' do
expect_any_instance_of(Google::Storage).to receive(:insert_object)
worker = UploadWorker.new
worker.perform
end

In case you just want to test that the method calls the method on any such objects.

2. bit more elaborated setup

In case you want to control or set up more expectations, you can do this

  it 'uploads to google cloud' do
the_double = instance_double(Google::Storage)
expect(Google::Storage).to receive(:new).and_return(the_double)
# + optional `.with` in case you wanna assert stuff passed to the constructor
expect(the_double).to receive(:insert_object)
worker = UploadWorker.new
worker.perform
end

Again - Dependency Injection is clearer, and you should aim for it. This is presented as another possibility.



Related Topics



Leave a reply



Submit