簡體   English   中英

Rspec控制器測試-如何存根和/或測試自定義對象

[英]Rspec controller test - how to stub and/or test custom objects

下面是過去!

控制器代碼:

class OrdersController
  def create
    ...
    @order.save
  end
end

規格代碼:

describe OrdersController do
  it "should call save method" do
    Order.any_instance.should_receive(:save)
    post :create
  end
end

但是,只要這么簡單...保存后便會執行一些自定義作業對象,因此代碼實際上如下所示:

控制器代碼:

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

我很想測試自定義對象是否正在接收帶有正確參數的方法鏈,但不確定如何,除非在規范代碼中創建如下內容:

before do
  class RoadrunnerEmailAlert
    def async
    end
  end
end

但這真是太虛構了,這當然是不對的。

萬一這對其他人有幫助...這是一個非常全面的答案。

上下文和設計說明

  1. 異步框架是Sucker Punch gem( http://brandonhilkert.com/blog/why-i-wrote-the-sucker-punch-gem/ )。 那時,這是我查看延遲工作,Sidekick等后最容易使用的東西
  2. 基本上它是這樣工作的:在Controller中引用一個Job,然后再引用其他任何內容(在我的情況下為某些PORO)
  3. 如果我真的進行嚴格測試,則需要測試A)控制器適當調用Job並傳遞正確的參數,B)Job調用適當的PORO並傳遞正確的參數。 但是,相反,我只是測試了Controller調用了適當的PORO並傳遞了正確的參數,即Jobs已經在工作了。

控制器代碼

@order.save
RoadrunnerEmailAlert.new.async.perform(@order.id, true)
CalendarInvite.new.async.perform(@order.id)
RoadrunnerTwilioAlert.new.async.perform(@order.id)

職務代碼

# 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

測試碼

我不知道為什么我會一直忘記(但僅在測試中)的真正大問題是類與類的實例。 對於PORO,由於我要實例化對象,因此我需要測試2個不同的“層”(首先,要適當地實例化該對象,其次要對該實例化對象進行適當的操作)。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM