I have a pretty simple rake task:
namespace :subscriptions do
desc 'Send expired subscription notifications'
task notify_trial_expired: :environment do
Subscription.where(expires_at: Date.today.all_day).each { |s| s.user.notify_trial_expired }
end
end
Where notify_trial_expired
is an instance method of the model User
.
The task works fine tested manually.
Now using rspec this is what I wrote:
require 'rails_helper'
describe "notify_trial_expired" do
let!(:subscription) { create(:subscription, expires_at: Date.today) }
let(:user) { double(:user) }
before do
allow(subscription).to receive(:user) { user }
allow(user).to receive(:notify_trial_expired)
Rake.application.rake_require "tasks/subscriptions"
Rake::Task.define_task(:environment)
Rake::Task['subscriptions:notify_trial_expired'].invoke
end
it "should notify all user which trial expires today" do
expect(user).to have_received(:notify_trial_expired)
end
end
I also tried with expect(user).to receive
and invoking the task after but both ways it shows the same error:
Failure/Error: expect(user).to have_received(:notify_trial_expired)
(Double :user).notify_trial_expired(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
I also checked to be sure the query Subscription.where(expires_at: Date.today.all_day)
returns my subscription
and it does. It's in received
or have_received
method the issue.
The issue is
allow(subscription).to receive(:user) { user }
The object subscription
here is not the same object returned from your query: Subscription.where(expires_at: Date.today.all_day)
. Yes in all practical terms they are the same record, but not from the tests point of view (the object_id's are different).
Your query looks dead simple, so I'd stub it (or move it to a model scope and test it there).
allow(Subscription).to receive(:where).with(expires_at: Date.today).and_return([subscription])
Now the rest of your stubs should work.