Testing thread execution in rspec

1,047 views
Skip to first unread message

siva

unread,
Jun 5, 2015, 7:01:42 AM6/5/15
to rs...@googlegroups.com

Hi 

Here is my following code:


# app/models/purchase_order.rb
class PurchaseOrder

  after_create :send_po_by_mail

  def send_po_by_mail

    Thread.new do
      begin
        Notifier.generate_po(self).deliver_now
        self.update_attributes(mail_status: SUCCESS)
      rescue
        self.update_attributes(mail_status: FAIL)
      end 
    end 
  end
end

# spec/models/purchase_order_spec.rb

example "update mail status as 'success' if sent successfully" do
  allow(Notifier).to receive(:generate_po).and_return(msg = double('ActionMailer::MessageDeliver'))
  allow(msg).to receive(:deliver_now).and_return(true)
  po = create(:purchase_order, job: create(:job))
  
  expect(po.reload.mail_status).to eq(PurchaseOrder::SUCCESS)
end 





When I ran rspec the above test case is failing. Where I am doing wrong? Could you help me?

Myron Marston

unread,
Jun 7, 2015, 3:13:08 AM6/7/15
to rs...@googlegroups.com, subbu98...@gmail.com
Threads provide no guarantees about when the OS will schedule them.  When you start using threads you need to synchronize at appropriate points if you want to assert that the thread completed it's work.  For this kind of situation, the standard way to do that is `Thread#join`:


It will block until the thread is complete, so that have a guarantee that the thread's work was finished.

Unfortunately, the thread instance is created in a private method and discarded so you don't have direct access to that thread from your spec in order to join on it.  You could use `Thread.list` to find that thread:


...but I'd say that your code isn't very testable, and it's far better to use your testing pain as an impetus to improve the design.

Most people do that kind of background work using something like Sidekiq rather than a thread:


Have you considered using that?

Myron

siva

unread,
Jun 8, 2015, 7:54:53 PM6/8/15
to rs...@googlegroups.com, subbu98...@gmail.com


Hi Myron

Thanks for helping me. I would definitely explore your options. Coming to Sidekiq, I have withdrawn Sidekiq option as my project doesn't need any type background processing anywhere apart from sending an email. 
Reply all
Reply to author
Forward
0 new messages