Rails中针对has_many :through关系编写RSpec测试

35

我对测试和Rails很陌生,但我正试图正确地掌握我的TDD过程。

我想知道你是否使用任何范例来测试has_many:通过关系(或者一般的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。

还有什么我忽略的吗?谢谢!

4个回答

73

我建议你看一下一个叫做Shoulda的宝石。它有很多用于测试关系和验证等内容的宏。

如果你只是想测试 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页面也非常有用。


你在测试时个人会有哪些常见的做法?我正在寻找开始测试时应该立即执行的基本操作。例如...测试我的关联似乎是合理的,但是我是否应该通过关联测试每个方法?或者什么时候停止测试呢?哈哈 - Mario Zigliotto
我非常喜欢使用这些快速的一行测试,因为它们非常容易设置。我总是从这些开始,并添加每个关系和验证,包括所有的通过关联。这不需要太多的工作,也不会给你的测试增加太多负担。然后,随着我添加功能,我会添加更多的单元测试。如果你在编写代码时为你的模型编写测试,它真的会迫使你编写简单、模块化的代码。 - Peter Brown
2
如何使用正确的语法编写 has_many through 关联? - Nimish
1
你如何在 RSpec 中处理源代码?例如:has_many :matched_indices, through: :covariances, source: :matched_indice, dependent: :destroy我们该如何测试它? - VoidZero

6

为了完整起见,在2020年,无需额外的gem即可实现此功能。

  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 Reflection API)

第二个例子确保“有一个(has_one)”不会与“属于(belongs_to)”混淆,反之亦然。

但是,它不仅限于“has_many:通过(:through)”的关系,可以用于应用于模型的任何关联关系。

(注意:这使用Rails 5.2.4的新RSpec 2.11语法)


2
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

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

Remarkable听起来很酷!你在rails3环境中使用它吗? - Mario Zigliotto
@Zaz,我迄今为止在Rails 2.2.3和2.3.9中使用过它。 我相信它也适用于Rails 3,但是我还没有尝试过。 - Wayne Conrad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接