2017-05-09 82 views
0

我想單元測試使用RSpec爲回報率的方法和有一個方法是這樣的:Ruby/Rails測試 - 範圍之外的訪問變量?

def create_record(obj, params) 
    begin 
     obj.add_attributes(params) 
     result = obj.save 
    rescue 
     MyMailer.failed_upload(@other_var, obj.api_class_name, params).deliver_now 
    end 
end 

create_record從不直接調用,而是通過其填充在適當@other_var另一種方法。

我應該如何去測試代碼以確保MyMailer被正確調用?我應該通過@other_var進入該方法,而不是依賴它在其他地方填充(又名:這是代碼味道?)?謝謝!

+0

存根'obj.save'引發一些錯誤,並檢查'​​ActionMailer :: Base.deliveries.count'是否增加了一個。 –

回答

0

在Ruby中,您可以使用Object#instance_variable_set來設置任何實例變量。

RSpec.describe Thing do 
    describe "#create_record" do 
    let(:thing) do 
     t = Thing.new 
     t.instance_variable_set(:@other_var, "foo") 
     t 
    end 
    # ... 
    end 
end 

這完全繞過了任何封裝,這意味着使用instance_variable_set可以被視爲代碼異味。

另一種替代方法是使用RSpecs嘲諷和存根設備,但剔除被測實際對象也是一種代碼異味。

您可以通過傳遞依賴作爲一個參數或通過構造函數注入避免這種情況:

class Thing 
    attr_accessor :other_var 

    def initialize(other_var: nil) 
    @other_var = other_var 
    end 

    def create_record(obj, attributes) 
    # ... 
    end 
end 

一個很好的模式因爲這是service objects

+0

所以我應該把它作爲參數傳遞給'create_record'來開始?這主要是帶走了嗎?謝謝! – skaz

+0

是的。 – max

+0

提供的代碼的另一個大問題是,您使用的是全部「rescue」語句,而沒有提供您想要解救的異常。這掩蓋了程序中的錯誤。 – max