gpt4 book ai didi

ruby - 我可以使用 FactoryGirl 创建无效值吗?

转载 作者:数据小太阳 更新时间:2023-10-29 08:08:23 27 4
gpt4 key购买 nike

我有电子邮件工厂(spec/factories/email.rb):

FactoryGirl.define do
factory :email, class: String do
skip_create

transient do
username 'user'
subdomain 'mail'
domain_name 'example.com'

host { [subdomain, domain_name].compact.join('.') }
end

trait(:with_blank_host) { host '' }
trait(:with_blank_username) { username '' }

initialize_with { new("#{username}@#{host}") }
end
end

我有规范 (spec/models/user_spec.rb):

RSpec.describe User, type: :model do
# ...

it { is_expected.to_not allow_value(FactoryGirl.create(:email, :with_blank_host)).for(:email) }
it { is_expected.to_not allow_value(FactoryGirl.create(:email, :with_blank_username)).for(:email) }
end

这样使用FactoryGirl是否正确?这是一种不良做法吗?

最佳答案

假设创建那些没有主机名/用户名的电子邮件背后的逻辑将不会在其他任何地方使用,除了测试。为什么要把它留在工厂里?

为什么不简单地做:

FactoryGirl.define do
factory :email, class: String do
skip_create

transient do
username 'user'
subdomain 'mail'
domain_name 'example.com'

host { [subdomain, domain_name].compact.join('.') }
end
initialize_with { new("#{username}@#{host}") }
end
end

RSpec.describe User, type: :model do
# ...

it 'should not allow blank host' do
is_expected.to_not allow_value(FactoryGirl.create(:email, host: '')).for(:email)
end

it 'should not allow blank username' do
is_expected.to_not allow_value(FactoryGirl.create(:email, username: '').for(:email)
end
end

最重要的是,有一个工厂来创建电子邮件字符串真的有意义吗?为什么不简单地使用字符串(这样更简单):

is_expected.to_not allow_value(FactoryGirl.create(:email, host: '')).for(:email)

对比

is_expected.to_not allow_value('test@').for(:email)

如果你想通过测试获得一致的 :email,为什么不把它放在用户中。

FactoryGirl.define do
factory :user

transient do
username 'user'
subdomain 'mail'
domain_name 'example.com'

host { [subdomain, domain_name].compact.join('.') }
end

before(:create) do |user, evaluator|
user.email = "#{username}@#{host}"
end
end
end

但是如果逻辑属于那些特定的测试,为什么要在工厂中抽象所有这些而不是简单地使用之前/回调。 根据经验,我只在工厂中放置将在规范文件中使用的逻辑,其他一切都在适当的前后回调中

RSpec.describe User, type: :model do
before :each do
# logic before each test of the file
end

context 'email validation'

before :each do
# logic before each test concerning the email validation
# useful to factor stuff that will be used multiple time
# e.g.
# @email_ok = 'user@example.com'
end

it 'should not allow blank host' do
# test specific setup
# useful for stuff only used in this test
# e.g
# email_no_host = 'user@'

# expectation
end
end
end

简而言之:

您所做的当然会奏效。这本身并不是坏习惯。恕我直言,这没有多大意义。

已编辑

您还可以在测试范围内添加一个助手,以免使模型太胖:

RSpec.describe User, type: :model do
context 'email validation'
def generate_email(**opts)
options = {username: 'user', subdomain: 'mail', domain_name 'example.com'}.merge(opts)
username = options[:username]
host = options[:host] || "#{options[:subdomain]}.#{options[:domain_name]}"

"#{username}@#{host}"
end

it 'should not allow blank host' do
is_expected.to_not allow_value(generate_email host: '').for(:email)
end

# Here goes 100 other use of generate_email
end
end

关于ruby - 我可以使用 FactoryGirl 创建无效值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27899368/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com