2012-07-06 21 views
35

Modelde doğrulamaları sınamak için RSpec (2.10.1) kullanıyorum ve diğer model doğrulamaları ile paylaşmak için bazı kodları ayıkladım. doğrulamaları ilk Firmalar masaya yazılı, bu nedenle kod şöyle edildi:Bir örnek değişkeni bir RSpec paylaşılan örneğine nasıl geçirilir

# support/shared_examples.rb 
shared_examples "a text field" do |field, fill, length| 
    it "it should be long enough" do 
    @company.send("#{field}=", fill * length) 
    @company.should be_valid 
    end 

    etc... 
end 

ve kullanım şöyledir:

# company_spec.rb 
describe Company do 
    before { @company = Company.new(init stuff here) } 

    describe "when address2" do 
    it_behaves_like "a text field", "address2", "a", Company.address2.limit 
    end 

    etc... 
end 

Ben paylaşılan bir parametre olarak @company geçmek istiyorum örnek bu yüzden bu gibi farklı modeller için kod, bir şeyler yeniden kullanabilirsiniz:

# support/shared_examples.rb 
shared_examples "a text field" do |model, field, fill, length| 
    it "it should be long enough" do 
    model.send("#{field}=", fill * length) 
    model.should be_valid 
    end 

    etc... 
end 

ve kullanım şöyledir:

# company_spec.rb 
describe Company do 
    before { @company = Company.new(init stuff here) } 

    describe "when address2" do 
    it_behaves_like "a text field", @company, "address2", "a", Company.address2.limit 
    end 

    etc... 
end 

Ancak, bunu yaptığımda undefined method 'address2' for nil:NilClass olsun. Görünüyor @company iletilmiyor (kapsam dahilinde değil?) Çalışmak için böyle bir şey nasıl alabilirim?

cevap

49

Sorun, örnek grubundaki self'un before kancasının içinde self'dan farklı olmasıdır, bu nedenle aynı ada sahip olsa bile aynı örnek değişkeni değildir.

# support/shared_examples.rb 
shared_examples "a text field" do |field, fill, length| 
    it "it should be long enough" do 
    model.send("#{field}=", fill * length) 
    model.should be_valid 
    end 
end 

# company_spec.rb 
describe Company do 
    describe "when address2" do 
    it_behaves_like "a text field", "address2", "a", Company.address2.limit do 
     let(:model) { Company.new(init stuff here) } 
    end 
    end 
end 
+1

Bazı parçalar bana mantıklı değil:

Sana bu gibi durumlar için let kullanmanızı öneririz. Eğer bu 'öz' farklıysa, farklı nerede? Neden '@ company.send()' ve '@ company.should' shared_examples' içinde çalışır? Önerinizde 'Company.new() 'i' company' ile ('before' bloğunu saklayarak) değiştirebilirim ve işe yarıyor. Anlayışım, tam olarak burada neler olduğu hakkında bir şey eksik. Görünüşe göre, 'benlik' sadece belirli bir yerde farklıdır (''' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'satırı' '. –

+6

RSpec'te 'self'in üstlendiği iki temel değer vardır ve bu, bir ruby ​​sınıfı tanımındaki kendiliğin iki değerine benzer. bir 'describe'/'context' /' shared_examples_for' ve karşılık gelen 'Sonu' (ancak' de Hazır blok) arasında, 'self' örneğin grubu - bir sınıf gövdesine self'' gibi (ancak bir yöntem tanımında değil) sınıfın kendisi. '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' sınıfın örneğidir . –

+3

Bunu düşünmenin başka bir yolu: RSpec'in gerçekleştirdiği iki geçişli bir işlem var. İlk olarak, tüm örnekleri tanımlamak için tüm iç içe geçmiş "anlatı"/"bağlam"/"paylaşılan_örnekler_sayısı" bloklarını değerlendirir; bu noktada, bu bağlamlarda 'self', karşılık gelen örnek grubudur. İkinci olarak, RSpec tüm tanımlanmış örnekleri çalıştırır ('' 'bloklar). Tanımlanan her örnek, ilgili örnek grubunun bir örneğinde değerlendirilir ve 'self', örneklemdir. –

İlgili konular