2012-07-01 66 views
13

我想在我的規範之間共享memoized方法。所以我試圖使用這樣的共享上下文在RSpec中自動共享上下文

RSpec.configure do |spec| 
    spec.shared_context :specs do 
    let(:response) { request.execute! } 
    end 
end 

describe 'something' do 
    include_context :specs 
end 

它工作正常。但是我有大約60個spec文件,所以我不得不明確地在每個文件中包含上下文。是否有一種方法可以自動包含spec_helper.rb中所有示例組的共享上下文(或至少let定義)?

像這樣的事情

RSpec.configure do |spec| 
    spec.include_context :specs 
end 
+0

這可能複製http://stackoverflow.com/questions/9965111/rspec-shared-context-and-include-context-for-all-specs但它仍然沒有答案。 – p0deje

回答

28

您可以通過configure-class-methodsConfiguration設置使用RSpec.configure全球before掛鉤:

RSpec.configure {|c| c.before(:all) { do_stuff }} 

letRSpec.configure不支持,但你可以設置一個全球let將其納入SharedContext module幷包括該模塊使用config.before

module MyLetDeclarations 
    extend RSpec::Core::SharedContext 
    let(:foo) { Foo.new } 
end 
RSpec.configure { |c| c.include MyLetDeclarations } 
+12

對於使用RSpec 3的人來說,它看起來像'RSpec :: Core :: SharedContext'已經消失,並已被'RSpec :: SharedContext'取代。 – womble

+0

這是一個不錯的解決方案。我在RSpec 3中遇到的一個小問題是,當傳遞一個標記來包含並在我的示例塊(而不是示例組塊)上包含該標記時,出現錯誤「NoMethodError:super:no superclass method \'foo'for #你的意思是? #foo'。修正只是爲了確保標記位於示例組上,而不是示例中。 –

+1

我遇到了與@GabeKopley相同的錯誤,但是我發現升級到RSpec 3.4.0解決了這個問題。 – phylae

5

你可以做到這一點幾乎是:有一個爲包括模塊機制,並納入模塊都有自己的回調機制。

假設例如,我們有我們想要用來運行我們所有的模型規格沒有數據庫連接的disconnected共享上下文。

shared_context "disconnected" do 
    before :all do 
    ActiveRecord::Base.establish_connection(adapter: :nulldb) 
    end 

    after :all do 
    ActiveRecord::Base.establish_connection(:test) 
    end 
end 

您現在可以創建一個模塊,該模塊將包含關於包含的上下文。

module Disconnected 
    def self.included(scope) 
    scope.include_context "disconnected" 
    end 
end 

最後,你可以包括模塊到正常方式的所有規格(我已經證明這樣做只爲模型,只是爲了顯示你能),這幾乎是正是你問什麼。

RSpec.configure do |config| 
    config.include Disconnected, type: :model 
end 

rspec-core 2.13.0和2.13.0 rspec-rails工作。

0

此外,如果您需要在before塊使用共享數據的能力內部規範,作爲我來說,嘗試加入這個(如果Rails項目):

module SettingsHelper 
    extend ActiveSupport::Concern 

    included do 
    attr_reader :default_headers 

    before :all do 
     @default_headers = Hash[ 
      'HTTP_HOST' => 'test.lvh.me' 
     ] 
    end 

    after :all do 
     @default_headers = nil 
    end 
    end 
end 

RSpec.configure do |config| 
    config.include SettingsHelper 
end 

或者嘗試類似的東西,看看@threedaymonk答案。

1

另一種方式去是automatically share examples via metadata。所以:

shared_context 'a shared context', a: :b do 
    let(:foo) { 'bar' } 
end 

describe 'an example group', a: :b do 
    # I have access to 'foo' variable 
end 

我最常用的方法是在rspec-rails中,根據示例組類型使用一些共享上下文。所以,如果你有config.infer_spec_type_from_file_location!,你可以簡單地做:

shared_context 'a shared context', type: :controller do 
    let(:foo) { 'bar' } 
end 

describe SomeController do 
    # I have access to 'foo' variable 
end 
5

在RSpec的3+,這可以如下實現 - 基於傑里米·彼得森的答案。

# spec/supprt/users.rb 
module SpecUsers 
    extend RSpec::SharedContext 

    let(:admin_user) do 
    create(:user, email: '[email protected]') 
    end 
end 

RSpec.configure do |config| 
    config.include SpecUsers 
end