0

私はMichael Hartlによる The Ruby on Rails Tutorial Book に従い、それを修正し、ユーザー認証のために Devise を追加し、電子メールの一意性テストで問題に遭遇しました。

# spec/models/user_spec.rb

require 'spec_helper'

describe User do
  before do
    @user = User.new(username: 'ExampleUser',
                     email:    'user@example.com',
                     password: 'passworD123')
    @user.save
  end

  subject { @user }

  it { should respond_to(:email) }
  it { should respond_to(:name) }
  it { should respond_to(:username) }
  it { should respond_to(:password) }

  it { should be_valid }

  describe 'username is already taken' do
    before do
      user_with_same_username = @user.dup
      user_with_same_username.username = @user.username.upcase
      user_with_same_username.email = 'a@b.c'
      user_with_same_username.save
    end

    it { should_not be_valid }
  end

  describe 'email address is already taken' do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.username = 'differentUsername'
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end

    it { should_not be_valid }
  end

  .
  .

失敗:

  1) User email address is already taken
     Failure/Error: it { should_not be_valid }
       expected valid? to return false, got true
     # ./spec/models/user_spec.rb:104:in `block (3 levels) in <top (required)>'

メールの一意性は、Devise がすでに行っているので必要ありませんが、設定されています。に変更user_with_same_email.saveしたuser_with_same_email.save!ところ、既に使用されているため、電子メール アドレスの検証エラーが発生しました。

1) User email address is already taken
   Failure/Error: user_with_same_email.save!
   ActiveRecord::RecordInvalid:
     Validation failed: Email has already been taken
   # ./spec/models/user_spec.rb:101:in `block (3 levels) in <top (required)>'

の戻り値user_with_same_email.saveは false で、it { should_not be_valid }このケースをチェックしますが、テストがまだ失敗するのはなぜですか?

4

1 に答える 1

2

実際の問題に関しては、理由は簡単です。適切なテストを行っていません。subject

その他のガイドライン:

  • 無効であることがわかっている場合は、オブジェクトを保存しないでください。時間を無駄にしているだけです。

  • 最初の仕様についても同じですが、永続化されたオブジェクトが本当に必要ですか? ないと思います..

  • 最後になりましたが、ファクトリの使用を検討してください。これは再利用可能であり、より一貫性のあるテストを行うことができます。

仕様は次のようになります。

require 'spec_helper'

describe User do
  let(:user_attributes) { {
      username: 'ExampleUser',
      email:    'user@example.com',
      password: 'passworD123'
    }
  }

  subject(:user) { User.new(user_attributes) }

  it { should respond_to(:email) }
  it { should respond_to(:name) }
  it { should respond_to(:username) }
  it { should respond_to(:password) }
  it { should be_valid }

  context 'with existing user in db' do
    before(:each) { user.save }

    describe 'username is already taken' do
      subject(:user_with_same_username) { User.new(user_attributes.merge(email: 'another@email.com')) }
      it { should_not be_valid }
    end

    describe 'email address is already taken' do
       subject(:user_with_same_email) { User.new(user_attributes.merge(username: 'another name')) }
       it { should_not be_valid }
    end
  end
end
于 2013-02-17T10:10:44.227 に答える