【问题标题】:One rspec roles test fails, but almost identical tests succeeds一项 rspec 角色测试失败,但几乎相同的测试成功
【发布时间】:2012-12-25 05:36:33
【问题描述】:

我刚刚添加了Rolify gem,并且正在运行一些 rspec 测试。

2个测试如下:

  describe "roles" do

    before(:each) do
      @user = FactoryGirl.create(:user)
    end

    it "should not approve incorrect roles" do
      @user.add_role :moderator
      @user.has_role? :admin
      should be_false
    end

    it "should approve correct roles" do
      @user.add_role :moderator
      @user.has_role? :moderator
      should be_true
    end

  end

测试结果是:

  1) User roles should not approve incorrect roles
     Failure/Error: should be_false
       expected: false value
            got: #<User id: nil, email: "", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, name: nil, position: nil, location: nil, admin: false, archived: false, public_email: false, created_at: nil, updated_at: nil>
     # ./spec/models/user_spec.rb:70:in `block (3 levels) in <top (required)>'

Finished in 1.37 seconds
7 examples, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:67 # User roles should not approve incorrect roles

Randomized with seed 13074

工厂.rb

FactoryGirl.define do

  factory :user do
    sequence(:name)       {|n| "Example User #{n}"}
    sequence(:email)      {|n| "email#{n}@program.com" }
    position              "Regular"
    location              "Anywhere, USA"
    public_email          false
    password              "foobar"
    password_confirmation "foobar"
    confirmed_at          Time.now
  end
end

第一个测试如何以 nil 对象失败,但第二个测试通过了?

编辑

经过进一步检查,should be_true 的任何测试都通过了,should be_false 的任何测试都失败了,无论添加的角色是否与检查的角色匹配。

【问题讨论】:

  • 你确定第二个正在过去吗?
  • 是的,数了数。尝试切换顺序,尝试在没有 FactoryGirl 和 User.create([@attr]) 的情况下进行操作,但所有这些仍然有一个测试通过而另一个测试失败。
  • 我也试过了,should_not be_true 和“should be_nil”,但还是做了同样的事情。

标签: ruby-on-rails rspec rolify


【解决方案1】:

当您的测试执行should be_true 时,发生的事情是应该调用被委托给主题对象(请参阅RSpec docs for implicit receiver)。在这种情况下,您的主题对象是尚未保存到数据库的用户实例。如果您的 user_spec.rb 文件以 describe User do 开头,RSpec 会自动提供 User.new 的默认主题(请参阅 RSpec docs for implicit subject)。

这意味着您的测试本质上是在执行User.new.should be_trueUser.new.should be_false。由于 User 对象的计算结果始终为 true,因此 should be_true 测试将始终通过(尽管可能不是出于您想要的原因),而 should be_false 将始终失败。

根据您的测试编写方式,您的意思可能更像这样:

describe "roles" do

  before(:each) do
    @user = FactoryGirl.create(:user)
  end

  it "should not approve incorrect roles" do
    @user.add_role :moderator
    @user.has_role?(:admin).should be_false
  end

  it "should approve correct roles" do
    @user.add_role :moderator
    @user.has_role?(:moderator).should be_true
  end

end

【讨论】:

  • 谢谢!我完全错过了。
【解决方案2】:

我假设示例组实际上嵌套在使用describe User do 声明的组中,是吗?

问题是每个示例的最后一行都是should xxx,但是should没有接收者,所以RSpec会为你替换一个User的实例。

你想要的是:

describe User do
  describe "roles" do
    before(:each) do
      @user = FactoryGirl.create(:user)
    end

    it "should not approve incorrect roles" do
      @user.add_role :moderator
      @user.has_role?(:admin).should be_false
    end

    it "should approve correct roles" do
      @user.add_role :moderator
      @user.has_role?(:moderator).should be_true
    end
  end
end

HTH, 大卫

【讨论】:

  • 哇...完全错过了。谢谢!!另外,我在某个地方看到了您对另一个问题的回答,谢谢。话虽如此,既然你们俩同时回答了同样的问题,我该如何决定选择哪一个呢?
  • cbascom 的回答比我的更详细。我会和那个一起去。
猜你喜欢
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多