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 ofcreateRewritten 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