【问题标题】:How do I write an Rspec controller test that makes sure an e-mail is sent?如何编写确保发送电子邮件的 Rspec 控制器测试?
【发布时间】:2012-06-04 15:59:00
【问题描述】:

目前在我的控制器规格中我有:

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

在我的控制器中,我有:

  # 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

我的测试当前产生以下输出:

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: "firstname1@example.com", 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

感谢您的关注。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 controller actionmailer rspec-rails


    【解决方案1】:

    您可以检查 ActionMailer::Base.deliveries.count 以确保它增加了 1。

    类似的东西(未经测试)

    expect {custom_mailer.deliver}.to change { ActionMailer::Base.deliveries.count }.by(1)
    

    【讨论】:

    • 我将 post :create, :customer_ticket =&gt; customer_ticket_attributes 放在了 expect 块中,这似乎可以完成这项工作。
    【解决方案2】:

    您设置的模拟与实际执行的不匹配。您实际上必须在您正在创建的模拟上调用 deliver

    类似

    message = mock('Message')
    CustomerMailer.should_receive(:sales_alert).and_return(message)
    message.should_receive(:deliver)
    

    应该会通过。

    如果您想检查传递给 sales_alert 的内容,您正在执行的操作将不起作用 - 活动记录只会按主键相等性比较对象,因此您在规范中创建的客户票不会是等于在您的控制器中创建的那个。

    你可以做的一件事是

    CustomerMailer.should_receive(:sales_alert) do |arg|
      ...
    end.and_return(message)
    

    rspec 将产生任何sales_alert 被调用的东西,你可以做任何你想做的检查

    另一种方法是存根CustomerTicket.new,以便您控制它返回的内容,例如

    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)
    

    最后,您可能会决定此警报发送确实应该属于 CustomerTicket 的实例方法,在这种情况下,您的控制器规范可以检查票证上是否调用了 send_sales_alert 方法。

    【讨论】:

      【解决方案3】:

      这是测试使用正确参数调用 Mailer 的方法。

      delivery = double
      expect(delivery).to receive(:deliver_now).with(no_args)
      
      expect(CustomerMailer).to receive(:sales_alert)
        .with(customer_ticket)
        .and_return(delivery)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-07
        • 2012-03-27
        • 2015-03-05
        相关资源
        最近更新 更多