在我的模型中,我有一个before_validation方法:
class Post < ActiveRecord::Base
before_validation :generate_url
...
private
def generate_url
return unless self.url.blank?
year = self.published_at.class == ActiveSupport::TimeWithZone ? self.published_at.year : DateTime.now.year
self.url = "#{year}/#{self.title.parameterize}"
end
rspec的/模型/ post.spec.rb
测试w rspec-rails(3.1.0)和factory_girl_rails(4.4.1),我得到了一个spec / models / post_spec.rb来验证Post模型和spec / factories / post.rb
由于before_validation ,验证测试失败
Post should require title to be set
Failure/Error: it { is_expected.to validate_presence_of(:title) }
NoMethodError:
undefined method `parameterize' for nil:NilClass
# ./app/models/post.rb:69:in `generate_url'
# ./spec/models/post_spec.rb:20:in `block (2 levels) in <top (required)>'
在generate_url方法中使用调试语句,我得到自己为nil ...所以看起来工厂帖子没有考虑在内
规格/模型/ post_spec.rb
require 'rails_helper'
RSpec.describe Post, :type => :model do
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to ensure_length_of(:title).is_at_least(5) }
it { is_expected.to validate_presence_of(:content) }
it { is_expected.to ensure_length_of(:content).is_at_least(10) }
it { is_expected.to validate_presence_of(:url) }
it { is_expected.to validate_uniqueness_of(:url) }
it { is_expected.to validate_presence_of(:published_at) }
end
规格/工厂/ post.rb
FactoryGirl.define do
factory :post do
user_id 1
title "myTitle"
content "myContent."
published false
published_at "2014-09-16 08:46:38"
end
end
# note : attribute url is generated with before_validation
答案 0 :(得分:5)
让它跳过before_validation
:
RSpec.describe Post, :type => :model do
before{ Post.skip_callback(:validation, :before, :generate_url) }
it { is_expected.to validate_presence_of(:user_id) }
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to ensure_length_of(:title).is_at_least(5) }
it { is_expected.to validate_presence_of(:content) }
it { is_expected.to ensure_length_of(:content).is_at_least(10) }
it { is_expected.to validate_presence_of(:url) }
it { is_expected.to validate_uniqueness_of(:url) }
it { is_expected.to validate_presence_of(:published_at) }
end
您还可以提供一个块,以便仅跳过块的验证,如下所示:
RSpec.describe Post, :type => :model do
Post.skip_callback(:validation, :before, :generate_url) do
it { is_expected.to validate_presence_of(:user_id) }
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to ensure_length_of(:title).is_at_least(5) }
it { is_expected.to validate_presence_of(:content) }
it { is_expected.to ensure_length_of(:content).is_at_least(10) }
it { is_expected.to validate_presence_of(:url) }
it { is_expected.to validate_uniqueness_of(:url) }
it { is_expected.to validate_presence_of(:published_at) }
end
end
答案 1 :(得分:0)
注意:自我不是零。 self.title是零
根据shoulda doc,可以通过设置这样的适当主题来修复规范
RSpec.describe Post, :type => :model do
subject { FactoryGirl.create :post }
it { is_expected.to validate_presence_of(:title) }
end
但是我尝试了这个,但错误仍然存在。 validate_presence_of
只是忽略主题并将其重置为Post.new
。它总是忽略了预期的事情。我会说这是一个错误的bug。 Wiil稍后检查他们的代码或至少提交问题。
与此同时,只要没有学校的方式就可以做到这一点
RSpec.describe Post, :type => :model do
describe #valiadations do
let!(:post) {Post.new.tap{|p|p.valid?} }
it "validated title" do
expect(post.errors_on[:title.size]).to eq(1)
end
end
end