Currently in my controller spec I have:
require 'spec_helper'
describe CustomerTicketsController do
login_user
describe "POST /create (#create)" do
# include EmailSpec::Helpers
# include EmailSpec::Matchers
it "should deliver the sales alert email" do
# expect
customer_ticket_attributes = FactoryGirl.attributes_for(:customer_ticket)
customer_mailer = mock(CustomerMailer)
customer_mailer.should_receive(:deliver).
with(CustomerTicket.new(customer_ticket_attributes))
# when
post :create, :customer_ticket => customer_ticket_attributes
end
end
end
In my controller I have:
# POST /customer_tickets
# POST /customer_tickets.xml
def create
respond_to do |format|
if @customer_ticket.save
CustomerMailer.sales_alert(@customer_ticket).deliver
format.html { redirect_to @customer_ticket, notice: 'Customer ticket was successfully created.' }
format.xml { render xml: @customer_ticket, status: :created, location: @customer_ticket }
else
format.html { render action: "new" }
format.xml { render xml: @customer_ticket.errors, status: :unprocessable_entity }
end
end
end
My test currently produces the following output:
Failures: 1) CustomerTicketsController POST /create (#create) should deliver the sales alert email Failure/Error: customer_mailer.should_receive(:deliver). (Mock CustomerMailer).deliver(#<CustomerTicket id: nil, first_name: "firstname1", last_name: "lastname1", company: nil, referral: nil, email: "[email protected]", phone: "555-5555", fax: nil, country: nil, address1: "555 Rodeo Dr.", address2: nil, city: "Beverly Hills", state: "CA", postcode: "90210", question: "The answer to the universe is 4.", type: nil, status: nil, priority: nil, number: nil, cs_rep_id: nil, created_at: nil, updated_at: nil>) expected: 1 time received: 0 times # ./spec/controllers/customer_ticket_controller_spec.rb:13:in `block (3 levels) in <top (required)>' Finished in 0.52133 seconds 1 example, 1 failure Failed examples: rspec ./spec/controllers/customer_ticket_controller_spec.rb:9 # CustomerTicketsController POST /create (#create) should deliver the sales alert email
Thank you for looking.
You could check the ActionMailer::Base.deliveries.count to ensure it has incremented by 1.
Something like this (untested)
expect {custom_mailer.deliver}.to change { ActionMailer::Base.deliveries.count }.by(1)
The mocks you're setting up don't match what is actually being executed. You'd have to actually be calling deliver
on that mock you're creating.
Something like
message = mock('Message')
CustomerMailer.should_receive(:sales_alert).and_return(message)
message.should_receive(:deliver)
should pass.
If you want to check what is passed to sales_alert
what you're doing won't work - active record only ever compares objects by primary key equality so the customer ticket you're creating in the spec won't be equal to the one created in your controller.
One thing you could do is
CustomerMailer.should_receive(:sales_alert) do |arg|
...
end.and_return(message)
rspec will yield whatever sales_alert
is called with and you can do whatever checks you want
Another way of doing it to is to stub out CustomerTicket.new
, so that you then control what it returns, for example
mock_ticket = mock(CustomerTicket)
CustomerTicket.should_receive(:new).with(customer_ticket_attributes).and_return(mock_ticket)
mock_ticket.should_receive(:save).and_return(true)
CustomerMailer.should_receive(:sales_alert).with(mock_ticket).and_return(message)
Finally you might decide that this alert sending should really belong in an instance method of CustomerTicket
in which case your controller spec could just check that a send_sales_alert
method was called on the ticket.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With