Rspec: How to Test If a Method Was Called

RSpec: how to test if a method was called?


it "should call 'bar' with appropriate arguments" do
expect(subject).to receive(:bar).with("an argument I want")
subject.foo
end

test that method was called inside another method with rspec

You cannot access tracker because it is a local variable.

You could stub your set_tracker method instead and return an instance double:

describe '#track_event' do
let(:tracker_double) { instance_double(Tracker) }

it 'should call event method' do
allow(foo).to receive(:set_tracker).and_return(tracker_double)
expect(tracker_double).to receive(:event)
foo.track_event
end
end

foo is your test subject.

Rails Rspec - How to test if Service has been called in another Service

Short anwser

describe 'call' do
let(:result) { CheckService.call(params) }
let(:params) { { user_id: "100" } }
## let(:check_user) { instance_double(CheckUser) } delete this

before do
allow(CheckUser).to receive(:call).and_return(true)
end

it do
result
expect(CheckUser).to have_received(:call)
end
end

Alternative

I think a better way to test this is to use DI (Dependency Injection), so you pass CheckUser as a dependency to CheckService. I prefer to write the whole test inside the it block too!

class CheckService
def initialize(params, check_handler:)
@params = params
@check_handler = check_handler
end

def self.call(params, check_handler: CheckUser)
new(params, check_handler: check_handler).call
end

def call
@check_handler.call(@params[:user_id])
end
end
describe 'call' do
it 'check user with params' do
check_user = class_double(CheckUser)
allow(check_user).to receive(:call).and_return(true)

params = { user_id: "100" }
CheckService.call(params, check_handler: check_user)

expect(check_user).to have_received(:call)
end
end

A blog post to read more about -> https://blog.testdouble.com/posts/2018-05-17-do-we-need-dependency-injection-in-ruby/

How do I test if a method is called on particular objects pulled from the DB in Rails with RSpec?

I realised that I'm really trying to test two aspects of the perform_dangerous_action method. The first is the scoping of the database fetch, and the second is that it calls the correct method on the User objects that come up.

For testing the scoping of the DB fetch, I should really just make a scope in the User class:

scope :not_fred, -> { where.not(name: "Fred") }

which can be easily tested with a separate test.

Then the perform_dangerous_action method becomes

def perform_dangerous_action
User.not_fred.each(&:dangerous_action)
end

and the test to check it calls the right method for not_fred users is

it "does the dangerous thing" do
user_double = instance_double(User)
expect(user_double).to receive(:dangerous_action)
allow(User).to receive(:not_fred).and_return([user_double])
UserDanger.perform_dangerous_action
end

RSpec - Check if method was called further down(up?) the call stack

RSpec allows you to use the any_instance_of set of matchers for setting this up.
This can be useful if you need to do this particular type of test and can't manually specify the instances via DI.

expect_any_instance_of(Widget).to receive(:name).and_return("Wobble")

See here

Using Rspec, how can I test a method which calls a method from another class in ruby

You have to call the method correctly. Transaction.new takes an amount, presumably a number, and some sort of Account object which has balance_after defined. You've given it two Symbols.

describe Transaction do
let(:account) { Account.new }
let(:amount) { 1.23 }
let(:transaction) { Transaction.new(amount, account) }
let(:timestamp) { Time.now.strftime('%d/%m/%Y') }

Then check that it returns what you expect. balance does not return true or false, it returns a balance. Specifically, it's just a pass through to account.balance_after(transaction), so test that.

  describe '#balance' do
it 'checks balance' do
expect(transaction.balance).to eq account.balance_after(transaction)
end
end

This might seem circular, but this is just an integration test. account.balance_after would be unit tested as part of Account's tests. There's no need to repeat those tests here.

How to check that a method has called another method with RSpec

Remember that expect and allow both stub the method call - they prevent it from actually running. If you want to check that one method was called, and also make sure that method calls another method, you need to use .and_call_original.

# Some setup
folder = "some fake folder" # not sure the data type
report = Reporting::GenerateReports.call
allow(Reporting::GenerateReports).to receive(:call).and_return(stub_report)

# Expectations
expect(Uploader).to receive(:execute).with(some_folder).and_call_original
expect(Uploader).to receive(:upload_file).with(report, folder)

That allow(Reporting::GenerateReports) line is needed because the report_record variable is defined inside your execute method (cannot pass in a custom value from the tests via dependency injection). To ensure that the correct argument is passed to upload_file, it therefore needs to be stubbed out.



Related Topics



Leave a reply



Submit