Below is passing!
Controller code:
class OrdersController
def create
...
@order.save
end
end
Spec code:
describe OrdersController do
it "should call save method" do
Order.any_instance.should_receive(:save)
post :create
end
end
But if only it were that easy... I have some custom job objects that are executed after the save, so the code actually looks like this:
Controller code:
class OrdersController
def create
...
@order.save
RoadrunnerEmailAlert.new.async.perform(@order.id, true)
CalendarInvite.new.async.perform(@order.id)
RoadrunnerTwilioAlert.new.async.perform(@order.id)
end
end
I would love to test that the custom objects are receiving the chain of methods with the right parameters, but not sure how, short of creating something in the spec code like this:
before do
class RoadrunnerEmailAlert
def async
end
end
end
But that's so contrived, it certainly isn't right... advice appreciated!
In case this helps other people... this is a very comprehensive answer.
Context & design notes
Controller code
@order.save
RoadrunnerEmailAlert.new.async.perform(@order.id, true)
CalendarInvite.new.async.perform(@order.id)
RoadrunnerTwilioAlert.new.async.perform(@order.id)
Job code
# app/jobs/roadrunner_email_alert.rb
class RoadrunnerEmailAlert
include SuckerPunch::Job
def perform(order_id, require_tos)
ActiveRecord::Base.connection_pool.with_connection do
OrderMailer.success_email(order_id, require_tos).deliver
end
end
end
# app/jobs/calendar_invite.rb
class CalendarInvite
include SuckerPunch::Job
def perform(order_id)
ActiveRecord::Base.connection_pool.with_connection do
CreateCalendar.new(order_id).perform
end
end
end
# app/jobs/roadrunner_twilio_alert.rb
class RoadrunnerTwilioAlert
include SuckerPunch::Job
def perform(order_id)
ActiveRecord::Base.connection_pool.with_connection do
CreateAlert.new(order_id).perform
end
end
end
Test code
The really big thing here that I don't know why I keep forgetting (but only in testing) is class vs. instance of class. For the POROs, since I'm instantiating the object, I needed to test 2 different "layers" (first that the object is instantiated appropriately, second that the instantiated object is acted upon appropriately).
require 'sucker_punch/testing/inline'
describe "Controller code" do
before do
OrderMailer.any_instance.stub(:success_email)
mock_calendar = CreateCalendar.new(1)
CreateCalendar.stub(:new).and_return(mock_calendar)
CreateCalendar.any_instance.stub(:perform)
mock_alert = CreateAlert.new(1)
CreateAlert.stub(:new).and_return(mock_alert)
CreateAlert.any_instance.stub(:perform)
end
it "should call appropriate async jobs" do
expect_any_instance_of(OrderMailer).to receive(:success_email).with(1, true)
expect(CreateCalendar).to receive(:new).with(1)
expect_any_instance_of(CreateCalendar).to receive(:perform)
expect(CreateAlert).to receive(:new).with(1)
expect_any_instance_of(CreateAlert).to receive(:perform)
post :create
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.