使用 Rspec 测试“关联”的正确方法?

Posted

技术标签:

【中文标题】使用 Rspec 测试“关联”的正确方法?【英文标题】:Correct way of testing "associations" with Rspec? 【发布时间】:2013-03-30 21:47:32 【问题描述】:

我正在尝试测试以下场景:

-> 我有一个名为 Team 的模型,当它由用户创建时才有意义。因此,每个 Team 实例都必须与一个 User 相关联。

为了测试,我做了以下操作:

describe Team do

...

  it "should be associated with a user" do
    no_user_team = Team.new(:user => nil)
    no_user_team.should_not be_valid
  end

...

end

这迫使我将团队模型更改为:

class Team < ActiveRecord::Base
  # Setup accessible (or protected) attributes for your model
  attr_accessible :name, :user

  validates_presence_of :name
  validates_presence_of :user

  belongs_to :user
end

这对您来说是否正确?我只是担心将 :user 属性设置为可访问(批量分配)。

【问题讨论】:

【参考方案1】:

我通常使用这种方法:

describe User do
  it "should have many teams" do
    t = User.reflect_on_association(:teams)
    expect(t.macro).to eq(:has_many)
  end
end

更好的解决方案是使用 gem shoulda,它可以让您简单地:

describe Team do
  it  should belong_to(:user) 
end

【讨论】:

应该实际测试什么?我想确保在创建新团队时它实际上属于用户。 Shoulda 将测试它,它将“确保存在 belongs_to 关系”(rubydoc.info/github/thoughtbot/shoulda-matchers/master/Shoulda/…)。因此,您可以放心地假设,当您创建一个新团队时,它将属于一个用户。 我刚刚对此进行了测试,我能够在不指定用户的情况下创建团队。应该只检查模型中是否存在belongs_to。我想确定一个团队有一个与之关联的用户...我相信我需要在创建团队时验证关联用户的存在... Hommer,我做了一些研究,看来您必须添加validates :user, presence: true以确保正确设置外键。检查这个***.com/questions/5176510/… 现在任何人的新语法都是expect(t.macro).to eq(:has_many)【参考方案2】:
  it  Idea.reflect_on_association(:person).macro.should  eq(:belongs_to) 
  it  Idea.reflect_on_association(:company).macro.should eq(:belongs_to) 
  it  Idea.reflect_on_association(:votes).macro.should   eq(:has_many) 

【讨论】:

我更喜欢这个解决方案而不是上面的那个。 shoulda gem 打破了我所有的权威测试,虽然有解决方法,但我宁愿避免使用看起来有问题的 gem。 这适用于 Rails 5.0.1、rspec 3.5.0 和 rspec-rails 3.5.2。【参考方案3】:
class MicroProxy < ActiveRecord::Base
    has_many :servers
end

describe MicroProxy, type: :model do
    it  expect(described_class.reflect_on_association(:servers).macro).to eq(:has_many) 
end

【讨论】:

urbanczykd 的回答重复 @Vasilisa 当前 Rspec 版本的社区约定鼓励使用 expect 而不是 should betterspecs.org/#expect 在测试同一类时,described_class 方法可用于不进行维护的目的用类名blog.eq8.eu/article/…锁定测试 我同意,但你在答案中什么也没说。请把你的解释从评论移到答案【参考方案4】:

RSpec 是一个 ruby​​ 测试框架,而不是一个 Rails 框架。 belongs_to 是一个 rails 构造,而不是 ruby​​ 构造。 像 shoulda-matchers 这样的 Gem 将 ruby​​ 和 rails 连接起来,帮助你编写好的测试。

记住以上内容并遵循官方文档,应该可以帮助您了解最新情况并了解您正在写的内容。

所以,下面是我要写的。

用户模型:

RSpec.describe User, type: :model do
  context 'associations' do
    it  should have_many(:teams).class_name('Team') 
  end
end

团队模型:

RSpec.describe Team, type: :model do
  context 'associations' do
    it  should belong_to(:user).class_name('User') 
  end
end

【讨论】:

以上是关于使用 Rspec 测试“关联”的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何测试 belongs_to 与 Rails 6 和 RSpec 4.1 的关联?

使用 rspec 进行 ActionMailer 测试 [关闭]

使用 RSpec 测试 DeserializationError

用导轨上的文件或图像进行Rspec的正确方法是什么?

RSpec 控制器测试 - 空白 response.body

RSpec控制器测试 - 空白响应.body