【问题标题】:rspec @variable returning nilrspec @variable 返回 nil
【发布时间】:2019-03-03 03:06:25
【问题描述】:

我的@attributes 变量有问题。我希望它可以访问以保持我的代码干燥,但目前,我必须重述变量并将其设置为“值”以使我的 rspec 测试正常工作。在不重复值的情况下,有什么更好的方法来做到这一点。

参考:Unexpected nil variable in RSpec

表明它在描述中不可访问,但需要另一种解决方案。 “指定”什么时候合适?我没用过。

describe "When one field is missing invalid " do 
    before(:each) do 
        @user = create(:user)
        @attributes = {"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}
    end
  values = {"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}
  values.keys.each do |f|
    p = values.except(f) 
    it "returns invalid when #{f.to_s} is missing" do 
              cr = CarRegistration::Vehicle.new(@user, p)
        cr.valid?
    end
  end
end

基于 cmets 的更新: 我还想在其他测试中使用值数组哈希。如果我按照说明将它放入循环中,我仍然需要在其他地方重复它。还有其他推荐吗?

更新:我尝试使用 let(),

  describe "When one field is missing" do

        let(:user) {Factorybot.create(:user)}
        let(:attributes) = {{"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}}

      attributes do |f|
        p = attributes.except(f) 
        it "returns invalid when #{f.to_s} is missing" do 
                  cr = CarRegistration::Vehicle.new(user, p)
            cr.valid?
        end
      end
  end

但得到以下错误。

attributes 在示例组中不可用(例如,describecontext 块)。它只能从单个示例(例如it 块)或在示例范围内运行的构造(例如beforelet 等)中获得。

【问题讨论】:

  • 您可以在 it 块内部运行键的循环,这样您就不需要使用 'values' 变量复制 @attributes。
  • @BKSpureon 是否有关于在集团之外为其他人重用密钥的建议?
  • 尝试使用 let 辅助方法以允许在块外重用:relishapp.com/rspec/rspec-core/docs/helper-methods/let-and-let
  • @BKSpureon,我试过 let 并得到上述错误。
  • 请参阅下面我的回答,或者按照塞尔吉奥的回答。

标签: ruby-on-rails rspec-rails ruby-on-rails-5.2


【解决方案1】:

在您的任何一个 sn-ps 中,您都不需要 attributes inside 规范。它是生成规范的数据。因此,它必须生活在上一层。

describe "When one field is missing" do

  let(:user) { Factorybot.create(:user) }

  attributes = { "has_car" => "true", "has_truck" => "true", "has_boat" => "true", "color" => "blue value", "size" => "large value" }

  attributes do |f|
    p = attributes.except(f)
    it "returns invalid when #{f.to_s} is missing" do
      cr = CarRegistration::Vehicle.new(user, p)
      cr.valid?
    end
  end
end

【讨论】:

  • 我不小心编辑了这个答案。请恢复到原始版本。道歉。
  • @BKSpureon:不用担心 :) JFYI,这种方法(循环数据结构并创建几个 it 块)在某种程度上被广泛使用。制作清晰的故障日志。不像你的版本;)(这会产生“预期的假是真的”)
  • @BKSpureon:关于规范缺少实际断言的好点!没注意。
  • 你是 100% 正确的,我已经为 OP 的利益添加了一个注释。
【解决方案2】:

您似乎已经认识到,根据您链接到的其他 SO 帖子,您无法在描述块中引用您的实例变量。只需将其设置为本地变量即可。

【讨论】:

    【解决方案3】:

    使用 let

    describe "When one field is missing" do
      let(:user) {Factorybot.create(:user)}
      let(:attributes) = {{"has_car"=>"true", "has_truck"=>"true", "has_boat"=>"true", "color"=>"blue value", "size"=>"large value"}}
      ## The variables are used INSIDE the it block.
      it "returns invalid when a key is missing" do
        attributes do |f|
          p = attributes.except(f)
          cr = CarRegistration::Vehicle.new(user, p)
          expect(cr.valid?).to eq(true)  # are you testing the expectation? Added this line.    
        end
      end
    end
    

    就我个人而言,我不喜欢编写可能因多种原因而失败的测试(如上所示)。塞尔吉奥是正确的。但是如果你想使用let,你必须在it块内使用它——这个例子说明了这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      相关资源
      最近更新 更多