1
votes

Here's rake task that's using threads to email async...Why is this rspec test for a rake task green if I put expect before the invoke? And is it appropriate to put the "expect" before "subject.invoke"?

rspec test

describe 'send foxes' do

subject { rake['send_foxes'] }

before do
   allow(SomeMailer).to receive_message_chain(:send_free_fox, :deliver_now)
end

it "should send fox" do
   expect(SomeMailer).to receive(:send_free_fox)
   subject.invoke
end
end

rake task

task :send_foxes do
    foxObject.find_in_batches(batch_size: 600) do |foxes|
      batch = Proc.new do
        fox_it(foxes)
      end
      Thread.new { batch.call }
    end
  end

  private
    def fox_it(foxes)
      foxes.each do |fox|
        if fox.status == 'kitten'
          user = User.find_by(id: fox.user_id)
          SomeMailer.send_free_fox(user: user).deliver_now
        end
      end
    end
end
2

2 Answers

1
votes

When using receive you always need to call expect before the code under test is run.

expect(foo).to receive(:bar) tells rspec to intercept and record the indicated method calls. If you do this after calling invoke then while invoke was running it will have been calling the original implementation of the method and rspec will not know whether it was called or not.

As you imply, this is different from other uses of expect which verify straightaway that some condition holds. With receive the verification phase is done after the example has run.

1
votes

Calling expect to receive on the SomeMailer here is creating ang an expectation on the the SomeMailer object that the send_free_box method is called within the test, the test would fail if the SomeMailer did not get the send_free_box method called.

If SomeMailer a mock, or the actual Mailer Object. In this scenario, if SomeMailer is a mock, then adding the expectation like this is fine, although you should also check the correct the arguments are passed in too, as well as return a correct mock for calling deliver on. Otherwise, if the SomeMailer is a real mailer, then you should test that emails are added to the mail queue correctly and not not touch the mail system at all.

Also, I'd recommend not using threads here, they make the code much harder to debug, introduce race conditions (especially when testing) and don't provide much performance increase.