When writing a test for the User model in Rspec
In a test to confirm the uniqueness of email
If you use FactoryBot.create ()
, the same test will be repeated multiple times thereafter.
The following error is displayed in the second and subsequent tests
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken
It seems that DB rollback is not done for each test
The following settings have been made in spec / rails_helper.rb
(default)
spec/rails_helper.rb
config.use_transactional_fixtures = true
rails db:migrate:reset RAILS_ENV=test
After that, the test was successful only once
spec/factories/users.rb
FactoryBot.define do
factory :user, class: User do
username {"test_user"}
email {"[email protected]"}
password {"password"}
password_confirmation {"password"}
end
factory :existed_user, class: User do
username { "existed_user" }
email { "[email protected]" }
password { "password" }
password_confirmation { "password" }
end
end
spec/models/user_spec.rb
subject(:user) { FactoryBot.build(:user, email: email) }
context "If the email is duplicated" do
existed_user = User.find_by(username: "existed_user") || FactoryBot.create(:existed_user)
let(:email) { existed_user.email }
it { is_expected.to be_invalid }
end
User.find_by(username: "existed_user") || FactoryBot.create(:existed_user)
Only when necessary in the part ofcreate
Rewritten to do
There seems to be a more essential solution, such as using gem, So far, the problem can be avoided by the method of 2).
Besides, defining factory sequentially was introduced in several articles. Only 5 things to remember when using FactoryBot-Qiita
Also, FactoryBot.create (: existed_user)
and
When doing FactoryBot.build (: existed_user)
You have to specify class: User
in FactoryBot.define
Encountered the following error
NameError: uninitialized constant ExistedUser
Since FactoryBot.create (: user)
and FactoryBot.build (: user)
are fine
It seems that it is judged to be the User class without permission
First RSpec Result I wrote a test for the User model as follows
require 'rails_helper'
describe User do
describe "#create" do
it "username, email, password,Can be registered if password confiramation exists" do
user = FactoryBot.build(:user)
expect(user).to be_valid
end
describe "username" do
subject(:user) { FactoryBot.build(:user, username: username) }
context "Cannot register if username does not exist" do
let(:username) { "" }
it { is_expected.to be_invalid }
end
context "Can be registered when username is 12 characters" do
let(:username) { "a"*12 }
it { is_expected.to be_valid }
end
context "Cannot be registered when username is 13 characters" do
let(:username) { "a"*13 }
it { is_expected.to be_invalid }
end
context "If the username is duplicated" do
existed_user = User.find_by(username: "existed_user") || FactoryBot.create(:existed_user)
let(:username) { existed_user.username }
end
end
describe "email" do
subject(:user) { FactoryBot.build(:user, email: email) }
context "If email does not exist" do
let(:email) { "" }
it { is_expected.to be_invalid }
end
context "If the email is duplicated" do
existed_user = User.find_by(username: "existed_user") || FactoryBot.create(:existed_user)
let(:email) { existed_user.email }
it { is_expected.to be_invalid }
end
end
describe "password" do
subject(:user) { FactoryBot.build(:user, password: password, password_confirmation: password_confirmation) }
context "If password does not exist" do
let(:password) { "" }
let(:password_confirmation) { "password" }
it { is_expected.to be_invalid }
end
context "If password exists but password confirmation does not exist" do
let(:password) { "passowrd" }
let(:password_confirmation) { "" }
it { is_expected.to be_invalid }
end
context "password is password_If it does not match confirmation" do
let(:password) { "password_a" }
let(:password_confirmation) { "password_b" }
it { is_expected.to be_invalid }
end
context "If password is 7 characters" do
let(:password) { "a"*7 }
let(:password_confirmation) { "a"*7 }
it { is_expected.to be_invalid }
end
context "If password is 8 characters" do
let(:password) { "a"*8 }
let(:password_confirmation) { "a"*8 }
it { is_expected.to be_valid }
end
end
end
end