Rails 3.1,RSpec:testing模型validation

我已经开始了在Rails中使用TDD的旅程,并遇到了一个关于模型validationtesting的小问题,我似乎找不到解决scheme。 比方说,我有一个用户模型,

class User < ActiveRecord::Base validates :username, :presence => true end 

和一个简单的testing

 it "should require a username" do User.new(:username => "").should_not be_valid end 

这正确地testing存在validation,但是如果我想更具体一点呢? 例如,在错误对象上testingfull_messages。

 it "should require a username" do user = User.create(:username => "") user.errors[:username].should ~= /can't be blank/ end 

我对初始尝试(使用should_not be_valid)的担心是RSpec不会产生描述性错误消息。 它只是说“预计有效?返回假,是真的。” 但是,第二个testing示例有一个小缺点:它使用create方法而不是新方法来获取错误对象。

我希望我的testing能够更具体地说明他们正在testing的内容,但同时不需要触摸数据库。

任何人有任何投入?

首先我想说你有一个邪恶的名字。

其次,恭喜您与ROR一起努力进入TDD。我承诺一旦您开始行动,您将不会回头。

最简单的快速和肮脏的解决scheme将是每个像这样的testing之前生成一个新的有效模型:

  before(:each) do @user = User.new @user.username = "a valid username" end 

但是我build议你为所有的模型设置工厂,这些模型会自动生成一个有效的模型,然后你可以混合个别的属性,看看你的validation。 我喜欢为此使用FactoryGirl :

基本上一旦你设置你的testing看起来像这样:

 it "should have valid factory" do FactoryGirl.build(:user).should be_valid end it "should require a username" do FactoryGirl.build(:user, :username => "").should_not be_valid end 

噢,这里是一个很好的railscast ,它解释得比我更好:

祝你好运 :)


更新:从版本3.0起,工厂女孩的语法已经改变。 我已经修改了我的示例代码来反映这一点。

testing模型validation(以及更多的主动logging)的更简单的方法是使用像应用程序或卓越的gem。

他们将允许testing如下:

 describe User it { should validate_presence_of :name } end 

尝试这个:

 it "should require a username" do user = User.create(:username => "") user.valid? user.errors.should have_key(:username) end 

在新版本的rspec中,你应该使用expect来代替,否则你会得到警告:

 it "should have valid factory" do expect(FactoryGirl.build(:user)).to be_valid end it "should require a username" do expect(FactoryGirl.build(:user, :username => "")).not_to be_valid end 

我在传统上处理function或请求规格中的错误内容规格。 所以,例如,我有一个类似的规格,我将在下面浓缩:

特征规范示例

 before(:each) { visit_order_path } scenario 'with invalid (empty) description' , :js => :true do add_empty_task #this line is defined in my spec_helper expect(page).to have_content("can't be blank") 

那么,我有我的模型spectesting是否有效,但是然后我的function规范testing错误消息的确切输出。 仅供参考,这些function规格要求可以在这里find水豚。

就像@ nathanvda说的那样,我会利用Thoughtbot的Shoulda Matchers的gem。 随着摇摆,你可以用以下方式编写你的testing,以testing是否存在,以及任何自定义错误消息。

 RSpec.describe User do describe 'User validations' do let(:message) { "I pitty da foo who dont enter a name" } it 'validates presence and message' do is_expected.to validate_presence_of(:name). with_message message end # shorthand syntax: it { is_expected.to validate_presence_of(:name).with_message message } end end