Rails RSpec 测试 has_many :through 关系

Posted

技术标签:

【中文标题】Rails RSpec 测试 has_many :through 关系【英文标题】:Rails RSpec Tests for a has_many :through Relationship 【发布时间】:2011-04-27 18:55:07 【问题描述】:

我是测试和 Rails 的新手,但我正试图让我的 TDD 流程正常运行。

我想知道您是否使用任何范式来测试 has_many :through 关系? (或者我想一般只是 has_many)。

例如,我发现在我的模型规范中,我肯定会编写简单的测试来检查关系的两端是否有相关方法。

即:

require 'spec_helper'

describe Post do

  before(:each) do
    @attr =  :subject => "f00 Post Subject", :content => "8ar Post Body Content" 
  end

  describe "validations" do
  ...    
  end

  describe "categorized posts" do

    before(:each) do
      @post  = Post.create!(@attr)
    end

    it "should have a categories method" do
      @post.should respond_to(:categories)
    end

  end

end

然后在我的类别规范中我进行反向测试并检查@category.posts

我还缺少什么?谢谢!!

【问题讨论】:

【参考方案1】:

我建议查看名为 Shoulda 的 gem。它有很多用于测试关系和验证之类的宏。

如果您只想测试 has_many 关系是否存在,那么您可以执行以下操作:

describe Post do
  it  should have_many(:categories) 
end

或者如果你正在测试一个 has_many :through,那么你会使用这个:

describe Post do
  it  should have_many(:categories).through(:other_model) 
end

我发现Shoulda Rdoc 页面也很有帮助。

【讨论】:

在测试的时候有没有你个人经常做的事情?我正在寻找我应该在开始时立即做的基线事情。诸如...测试我的关联似乎是合理的,但是我应该通过关联测试每种方法吗?或者怎么知道什么时候停止?!大声笑 我真的很喜欢使用这些快速的单行测试,因为它们非常容易设置。我总是从这些开始并添加每一个关系和验证,包括所有通过关联。它不需要太多工作,也不会为您的测试增加太多开销。然后当我添加功能时,我将添加更多的单元测试。如果您在编写代码的同时为模型编写测试,这确实会迫使您编写简单的模块化代码。 如何写has_many通过与expect syntex的关联? 如何处理 rspec 中的源代码。即如果例如:has_many :matched_indices, through: :covariances, source: :matched_indice,dependent: :destroy 我们如何测试这个?【参考方案2】:

remarkable 会很好地做到这一点:

describe Pricing do

  should_have_many :accounts, :through => :account_pricings
  should_have_many :account_pricings
  should_have_many :job_profiles, :through => :job_profile_pricings
  should_have_many :job_profile_pricings

end

通常,您只需将所有关系从模型复制到规范,然后将“has”更改为“should_have”,将“belongs_to”更改为“should_belong_to”,等等。为了回答它正在测试 Rails 的指控,它还会检查数据库,确保关联有效。

还包括用于检查验证的宏:

should_validate_numericality_of :amount, :greater_than_or_equal_to => 0

【讨论】:

非凡的声音很酷!您是否将它与 rails3 环境一起使用? @Zaz,到目前为止,我已经将它与 Rails 2.2.3 和 2.3.9 一起使用。我相信它也适用于 Rails 3,但我还没有尝试过。【参考方案3】:
describe "when Book.new is called" do
  before(:each) do
    @book = Book.new
  end

  #otm
  it "should be ok with an associated publisher" do
    @book.publisher = Publisher.new
    @book.should have(:no).errors_on(:publisher)
  end

  it "should have an associated publisher" do
    @book.should have_at_least(1).error_on(:publisher)
  end

  #mtm
  it "should be ok with at least one associated author" do
    @book.authors.build
    @book.should have(:no).errors_on(:authors)
  end

  it "should have at least one associated author" do
    @book.should have_at_least(1).error_on(:authors)
  end

end

【讨论】:

【参考方案4】:

为了完整起见,在 2020 年,无需额外宝石即可实现。

  it "has many categories" do
    should respond_to(:categories)
  end

甚至更明确:

it "belongs to category" do
  t = Post.reflect_on_association(:category)
  expect(t.macro).to eq(:belongs_to)
end

(见Ruby API on Reflection)

第二个示例确保“has_one”不是 与“belongs_to”混淆,反之亦然

然而,它不仅限于 has_many :through 关系,还可以用于应用于模型的任何关联。

(注意:这是在 Rails 5.2.4 中使用 new rspec 2.11 syntax)

【讨论】:

以上是关于Rails RSpec 测试 has_many :through 关系的主要内容,如果未能解决你的问题,请参考以下文章

设置 RSpec 以测试 gem(不是 Rails)

Rails/Rspec:测试延迟作业邮件

Rails:在 RSpec 测试查看编辑表单时出错

Rails 3.1,RSpec:测试模型验证

使用 Rspec 测试 Rails 3.1 可安装引擎

使用 rspec 测试文件上传 - rails