【问题标题】:rspec `its` syntax with dynamic conditions具有动态条件的 rspec `its` 语法
【发布时间】:2011-12-09 13:21:36
【问题描述】:

我一直非常喜欢使用带有 rspec 的 contextssubjectsits 来真正清理我的测试代码。典型例子:

context "as a user" do
  subject{ Factory :user }

  its(:name){ should == "Bob" }
end

但我想不通的是如何使这个条件动态化(即基于其他对象)。 its 似乎对块内的属性进行了实例化,因此我无法访问它周围的所有内容。我想做这样的事情:

its(:name){ should == subject.contact.name }

但我看不到任何实现这一目标的方法。有谁知道是否有一些通过此实例 eval 代理的方法可以访问原始对象?或者如果有任何其他方式我可以使用我正在检查的属性实例范围之外的方法?

附加信息

似乎its 块中的subject 更改为实际属性(在这种情况下为name

有趣的是,我可以访问我的任何 let 方法,但同样,我无法访问有问题的原始 subject

【问题讨论】:

  • 您能重新表述一下您的问题吗?听起来您正在做一些有趣的事情,但是您的示例很糟糕,因为您正在尝试测试内部实现而不是外部行为。
  • 我的问题与这个特定的实现无关。相反,我想在我的its 块中引用我的user 设置作为主题,但经过一些探索后,its 中的主题现在变成了属性(在这种情况下为name
  • 请注意,这可能不是一个好主意,因为它不会在您的规范报告中为您提供有意义的描述:您将在报告中看到 should == "Bob",而您真正想要的看到是should equal the contact's name - 我知道its 语法无法做到这一点。我喜欢its,但由于这个限制,我只用它来匹配常量。

标签: ruby scope rspec2


【解决方案1】:

您几乎是在回答自己,在设置主题之前使用let 分配。然后你可以在任何地方引用它:

context "as a user" do
  let(:user) { Factory(:user) }
  subject { user }
  its(:name) { should == user.contact.name }
end

我也是contextsubjectits的情人!

【讨论】:

  • 是的,我想这是有道理的。只是不确定是否有更好的方法。
  • rspec 现在支持subject(:user) {user}.. 因此可以删除let(:user).. 声明
  • @David 抱歉,但实际上鼓励对 SO 进行编辑。 stackoverflow.com/privileges/edit
【解决方案2】:

您可以在主题块中设置一个实例变量:

context 'as a user' do
  subject { @user = FactoryGirl.create(:user) }

  its(:name) { should == @user.name }
end

【讨论】:

  • let() 优于实例变量。
【解决方案3】:

不确定是否有办法完全按照您的要求做,因为块中的“主题”变成了User#name 的返回值。

相反,我使用let 方法以及以下规范样式来编写这种测试:

describe User do

  describe '#name' do
    let(:contact) { Factory(:contact, name: 'Bob') }
    let(:user) { Factory(:user, contact: contact) }

    subject { user.name }

    it { should == 'Bob' }
  end

end

这当然对您的联系人所代表的内容做了一些假设(这里是关联或类似的)。您也可以选择存根 User#contact 的返回值,而不是依赖 FactoryGirl 来设置“真实”关联。

无论您在这些方面做出何种选择,这种策略对我来说都很有效。我发现它可以让我更简洁地了解正在测试的内容,同时保留有关预期返回值来自何处的信息(供其他开发人员和未来的自己使用。

【讨论】:

  • 谢谢,我想更多的是回答我的问题,比如:it{ should == contact.name } 应该可以工作,因为我似乎可以在这个范围内访问contact
  • 是的,这应该可行,但在我看来,您应该明确返回值...例如:验证它确实是 'Bob' 并且不要依赖 Contact#name 返回您的断言中的正确值。在这种情况下没什么大不了的,但请考虑这两种方法都可能无意中返回 nil - 即使返回值不正确,测试也会通过。
猜你喜欢
  • 2023-01-20
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
相关资源
最近更新 更多