2014-09-05 46 views
1

在rspec的3.1.0中的語法,一個規範可以使用#allow存根的方法:能夠想到一類

describe do 
    specify do 
    o = Object.new 
    allow(o).to receive(:foo) 
    o.foo 
    end 
end 

這工作得很好。但是,如果短線在一個類中的方法內,則#allow方法沒有定義:

describe do 

    class Baz 
    def allow_bar(o) 
     allow(o).to receive(:bar) 
    end 
    end 

    specify do 
    o = Object.new 
    Baz.new.allow_bar(o) 
    o.bar 
    end 

end 

的錯誤是:

Failure/Error: allow(o).to receive(:bar) 
NoMethodError: 
    undefined method `allow' for #<Baz:0x8de6720> 
# ./bar_spec.rb:5:in `allow_bar' 
# ./bar_spec.rb:11:in `block (2 levels) in <top (required)>' 

爲什麼我在一個類中的磕碰

該測試將其測試double定義爲常規類,而不是使用rspec的「double」方法。這是因爲測試double有一個線程。內部測試雙是這樣的代碼:

if command == :close 
    # Note: Uses the old (rspec 2) syntax. Needs to be converted 
    # to rspec 3 syntax using the #allow method. 
    socket.stub(:getpeername).and_raise(RuntimeError, "Socket closed") 
end 

這可以防止錯誤地使用套接字會話被關閉後,被測代碼。

私有解決方案

我可以給測試雙接入在RSpec中,模擬調用私有API來#allow:

class Baz 
    RSpec::Mocks::Syntax.enable_expect self # Uses private API 
    def allow_bar(o) 
     allow(o).to receive(:bar) 
    end 
    end 

這工作。然而,明確標記爲RSpec的/嘲笑/ syntax.rb私有API:

# @api private 
    # Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc). 
    def self.enable_expect(syntax_host = ::RSpec::Mocks::ExampleMethods) 
    ... 

問題

在Rspec的3.1,有一個公共 API我可以用它來使期望類中可用的語法?

+1

應該有注入'socket'到類的方式。然後,你將不再需要在課堂中使用'allow'。 AFAIK RSpec 3試圖儘可能多地刪除猴子補丁,這是一件好事。這聽起來像是一個懶惰的回答,但是當你的代碼很難測試時,大多數情況下這是你的代碼有其他問題的跡象。 – 2014-09-05 19:44:26

+0

@ p11y通常這是真的。我可能會在CR上發佈完整的代碼,看看其他人能否看到我看不到的更好的設計。 – 2014-09-05 19:55:25

+0

@ p11y我開始編寫CR問題,然後實現了一個更好的方法(在這種情況下,公開兩個私有方法做了竅門,對類的API沒有真正的破壞)。另一個問題在詢問中回答。謝謝你的幫助。我仍然對這個問題的答案感興趣,因爲下一次我想做錯了。 – 2014-09-06 00:28:45

回答

1

您可以通過在幾RSpec的模塊/類混合到類實現這一點:

class MyClass 
    include RSpec::Mocks::ExampleMethods::ExpectHost 
    include RSpec::Matchers 

    def some_test 
    expect(1).to eql(1) 
    end 
end 
相關問題