I have the following class:
class UserRewards
def self.grant(reward_id:, submission_id:, user_id:)
puts 'Hello from UserRewards.grant'
debugger
ActiveRecord::Base.transaction do
puts 'ActiveRecord::Base.transaction'
end
end
end
And the following test:
require 'rails_helper'
RSpec.describe UserRewards do
describe '.grant' do
it 'grants a reward to a user' do
user = build_stubbed(:user)
submission = build_stubbed(:submission)
reward = build_stubbed(:reward)
UserRewards.grant(
reward_id: reward.id,
submission_id: submission.id,
user_id: user.id,
)
expect(ActiveRecord::Base).to receive(:transaction)
end
end
end
I simply want to verify that ActiveRecord::Base
has received :transaction
, when I run the test, but no matter what I do, or how I try to restructure this test, I always get the following failure:
1) UserRewards.grant grants a reward to a user
Failure/Error: expect(ActiveRecord::Base).to receive(:transaction)
(ActiveRecord::Base (class)).transaction(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
I've verified the method is being run via the debugger:
(rdbg) n # next command
[1, 10] in ~/workspace/my-app/lib/services/user_rewards.rb
1| class UserRewards
2| def self.grant(reward_id:, submission_id:, user_id:)
3| debugger
4| ActiveRecord::Base.transaction do
=> 5| puts 'ActiveRecord::Base.transaction'
6| end
7| end
8|
9| def self.revoke(reward_id:, submission_id:, user_id:)
=>#0 block in grant at ~/workspace/my-app/lib/services/user_rewards.rb:6
#1 block in within_new_transaction at ~/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/activerecord-7.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:319
# and 74 frames (use `bt' command for all frames)
I know I must be doing something wrong here. I don't have to stub the method on ActiveRecord::Base, do I? I'm not the most proficient tester, but I'm trying to get better. And headaches like this are what always put me off from having well tested code...
CodePudding user response:
If you just need to know that a transaction was called you can stub this method and then check that it was called. Your it
is very fat, it's better to use AAA-principle
require 'rails_helper'
describe UserRewards do
describe '.grant' do
let(:user) { build_stubbed(:user) }
let(:submission) { build_stubbed(:submission) }
let(:reward) { build_stubbed(:reward) }
before do
allow(ActiveRecord::Base).to receive(:transaction)
described_class.grant(
reward_id: reward.id,
submission_id: submission.id,
user_id: user.id,
)
end
it 'calls database transaction' do
expect(ActiveRecord::Base).to have_received(:transaction).once
end
end
end