为什么数据库检查不会在rspec中引发错误,但会在rails控制台中引发错误?

时间:2017-04-09 00:26:35

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

我正在使用rails 5.0.2,ruby 2.4.0和postgresql 9.6.2编写博客应用程序。我使用Rspec编写了一些测试来检查postgres检查约束是否阻止将无效数据保存到数据库中。 null约束在Rspec中传递,但长度检查约束失败。但是,当我尝试在rails控制台中保存相同的数据时,我会收到错误。

我使用Rspec编写了以下测试数据库检查:

require 'rails_helper'

RSpec.describe User, type: :model do

  describe 'database checks' do

    context 'without email' do
      let :user { build :user, email: nil }

      it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
    end

    context 'without name' do
      let :user { build :user, name: nil }

      it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid}
    end

    context 'without encrypted password' do
      let :user { build :user, encrypted_password: nil }

      it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
    end

    context 'empty email' do
      let :user { build :user, email: '' }

      it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
    end

    context 'empty name' do
      let :user { build :user, name: ''}

      it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
    end
  end
end

用户工厂:

FactoryGirl.define do
  factory :user, do
    email "test@example.com"
    password "test password"
    name "Test"
    created_at { 5.seconds.ago }
    updated_at { DateTime.now }
    description "Test description
  end
end

用户表:

CREATE TABLE users (
    id integer NOT NULL,
    email character varying DEFAULT ''::character varying NOT NULL,
    encrypted_password character varying DEFAULT ''::character varying NOT NULL,
    reset_password_token character varying,
    reset_password_sent_at timestamp without time zone,
    remember_created_at timestamp without time zone,
    name character varying NOT NULL,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL,
    description text,
    CONSTRAINT email_length_check CHECK ((length((email)::text) > 0)) NO INHERIT,
    CONSTRAINT name_length_check CHECK ((length((name)::text) > 0)) NO INHERIT
);

Rspec输出:

Randomized with seed 21829
F.F..

Failures:

  1) User database checks empty email should raise ActiveRecord::StatementInvalid
     Failure/Error: it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
       expected ActiveRecord::StatementInvalid but nothing was raised
     # ./spec/models/user_spec.rb:28:in `block (4 levels) in <top (required)>'

  2) User database checks empty name should raise ActiveRecord::StatementInvalid
     Failure/Error: it { expect {user.save validate: false}.to raise_error ActiveRecord::StatementInvalid }
       expected ActiveRecord::StatementInvalid but nothing was raised
     # ./spec/models/user_spec.rb:34:in `block (4 levels) in <top (required)>'

Finished in 0.41576 seconds (files took 14.93 seconds to load)
5 examples, 2 failures

Failed examples:

rspec ./spec/models/user_spec.rb:28 # User database checks empty email should raise ActiveRecord::StatementInvalid
rspec ./spec/models/user_spec.rb:34 # User database checks empty name should raise ActiveRecord::StatementInvalid

Randomized with seed 21829

Rails控制台输出:

Running via Spring preloader in process 11864
Loading development environment (Rails 5.0.2)
[1] pry(main)> user = FactoryGirl.build :user, email: ''
=> #<User id: nil, email: "", name: "Test", created_at: "2017-04-09 00:19:37", updated_at: "2017-04-09 00:19:42", description: "Test description">
[2] pry(main)> user.save validate: false
   (0.2ms)  BEGIN
  SQL (1.9ms)  INSERT INTO "users" ("encrypted_password", "name", "created_at", "updated_at", "description") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["encrypted_password", "$2a$11$UCKPTyuQyfgyWibv3mlv4OFavF2nLtGwFhHvYJMmCepwevJhSja2u"], ["name", "Test"], ["created_at", 2017-04-09 00:19:37 UTC], ["updated_at", 2017-04-09 00:19:42 UTC], ["description", "Test description"]]
   (0.2ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::CheckViolation: ERROR:  new row for relation "users" violates check constraint "email_length_check"
DETAIL:  Failing row contains (9, , $2a$11$UCKPTyuQyfgyWibv3mlv4OFavF2nLtGwFhHvYJMmCepwevJhSja2u, null, null, null, Test, 2017-04-09 00:19:37.826153, 2017-04-09 00:19:42.826772, Test description).
: INSERT INTO "users" ("encrypted_password", "name", "created_at", "updated_at", "description") VALUES ($1, $2, $3, $4, $5) RETURNING "id"
from /Users/edgarlepe/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'
[3] pry(main)> user = FactoryGirl.build :user, name: ''
=> #<User id: nil, email: "test@example.com", name: "", created_at: "2017-04-09 00:20:21", updated_at: "2017-04-09 00:20:26", description: "Test description">
[4] pry(main)> user.save validate: false
   (0.2ms)  BEGIN
  SQL (1.9ms)  INSERT INTO "users" ("email", "encrypted_password", "name", "created_at", "updated_at", "description") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["email", "test@example.com"], ["encrypted_password", "$2a$11$gmMGIjSKycqLmOybtxuWAee.OMHdyktzM2ZeR3ZawHEGkYk1SlMki"], ["name", ""], ["created_at", 2017-04-09 00:20:21 UTC], ["updated_at", 2017-04-09 00:20:26 UTC], ["description", "Test description"]]
   (0.2ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::CheckViolation: ERROR:  new row for relation "users" violates check constraint "name_length_check"
DETAIL:  Failing row contains (10, test@example.com, $2a$11$gmMGIjSKycqLmOybtxuWAee.OMHdyktzM2ZeR3ZawHEGkYk1SlMki, null, null, null, , 2017-04-09 00:20:21.010989, 2017-04-09 00:20:26.011515, Test description).
: INSERT INTO "users" ("email", "encrypted_password", "name", "created_at", "updated_at", "description") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"
from /Users/edgarlepe/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'

用户模型:

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :articles
end

0 个答案:

没有答案