Ruby on Rails允许RSpec测试的质量分配

时间:2011-09-17 13:58:12

标签: ruby-on-rails rspec factory-bot

我正在使用RSpec测试我的Rails应用程序,但后来我遇到了一个问题。我想要一个一致的数据库,因此我强制要求某些列不能为空。

我有一个评论模型,评论可能是另一条评论的答案。 Morevoer评论的IP地址不应为空。这是迁移:

create_table :comments do |t|
  t.string :name, :limit => 20, :null => false
  t.string :comment, :limit => 8192, :null => false
  t.string :ip, :null => false
  t.integer :answer_to_comment_id
end

然后我创建了Comment模型,只有namecomment可访问

class Comment < ActiveRecord::Base
  attr_accessible :name, :comment

  belongs_to :answer_to, :class_name => "Comment", 
                         :foreign_key => "answer_to_comment_id"

  has_many :answers, :class_name => "Comment", 
                     :foreign_key => "answer_to_comment_id", 
                     :dependent => :destroy
end

我的factories.rb看起来像这样:

Factory.define :comment do |comment|
  comment.name    "test"
  comment.comment "test"  
  comment.ip      "0.0.0.0"
end

现在我在RSpec测试comment_spec.rb

中遇到以下问题
describe "some test" do
  before(:each) do
    @answer = @comment.answers.create(Factory.attributes_for(:comment))
  end
end

这将失败,因为:ip不在attr_accessible列表中,因此ActiveRecord无法在数据库中创建记录。我可以将:ip添加到列表中,但由于批量分配,这可能会导致一些安全问题。或者我可以手动添加:ip,但如果有更多属性,例如ip

,这可能会成为很多工作

所以我寻找绕过attr_accessible列表的可能性。或者如果你有更好的设计模式,请告诉我

谢谢

3 个答案:

答案 0 :(得分:3)

我在搜索同一问题的解决方案时遇到了这个问题。我知道它已经很老了,但是为了什么值得我挖掘代码并决定以这种方式解决问题:

before :each do
  ActiveModel::MassAssignmentSecurity::WhiteList.any_instance.stub(:deny?).and_return(false)
end

也许这会对在这里结束的其他人派上用场。

答案 1 :(得分:1)

只需使用:

describe "some test" do
  before(:each) do
    @answer = @comment.answers << Factory(:comment)
  end
end

或者如果您需要多条评论,请说n

describe "some test" do
  before(:each) do
    @answer = @comment.answers = FactoryGirl.create_list(:comment, n)
  end
end

答案 2 :(得分:0)

我在测试过程中基本上使用this的变体(以及其他一些调整)。

(但Fabio的答案更清晰 - 这是工厂的事情之一,制造东西 - 不仅仅是属性的持有者:)