检查RSpec中的ActiveRecord关联

我正在学习如何使用Rspec编写测试用例。 我有一个简单的post评论脚手架,其中一个post可以有很多评论。 我正在使用Rspec进行测试。 我应该如何检查Post :has_many :comments 。 我应该将Post.comments方法存根,然后通过返回注释对象数组的模拟对象来检查它吗? 真的需要测试AR协会吗?

由于ActiveRecord关联应该由Rails测试套件(它们是)进行良好测试,因此大多数人并不认为有必要确保它们正常工作 – 它只是假设它们会。

如果你想确保你的模型正在使用那些关联,那就是不同的东西,而你想要测试它并没有错。 我喜欢使用shoulda gem这样做。 它可以让你做这样的事情:

 describe Post do it { should have_many(:comments).dependent(:destroy) } end 

测试协会通常是一种良好的做法,特别是在TDD受到高度重视的环境中 – 其他开发人员在查看相应的代码之前通常会查看您的规范。 测试关联可确保您的spec文件最准确地反映您的代码。

您可以通过两种方式测试关联:

  1. 使用FactoryGirl:

     expect { FactoryGirl.create(:post).comments }.to_not raise_error 

    这是一个相对肤浅的测试,将与工厂一样:

     factory :post do title { "Top 10 Reasons why Antelope are Nosy Creatures" } end 

    如果您的模型缺少与注释的has_many关联,则返回NoMethodError。

  2. 您可以使用ActiveRecord #reflect_on_association方法更深入地了解您的关联。 例如,通过更复杂的关联:

     class Post has_many :comments, through: :user_comments, source: :commentary end 

    您可以深入了解您的关联:

     reflection = Post.reflect_on_association(:comment) reflection.macro.should eq :has_many reflection.options[:through].should eq :user_comments reflection.options[:source].should eq :commentary 

    并测试相关的任何选项或条件。

如果您不想使用像shoulda这样的外部gem来测试您的关联(请参阅Robert Speicher的答案以获取详细信息),另一个选择是使用reflect_on_association获取相关关联的AssociationReflection对象,然后断言:

 describe Post do it "should destroy its comments when it is destroyed" do association = Post.reflect_on_association(:comments) expect(association).to_not be_nil expect(association.options[:dependent]).to eq :destroy end end 

大多数人不测试关联,因为Rails已经进行了unit testing以确保这些方法正常工作。 如果你正在做一些复杂的事情,比如涉及proc或其他东西,你可能想要明确地测试它。 通常你可以这样做

 a = Post.new a.comments << Comment.new assert a.save assert a.comments.size == 1 

或类似的东西。