Ruby on rails 如何使用冗余的'let!'干涸RSpec测试方法调用?
我如何在我的Rails应用程序中使用RSpec创建这样的测试块:Ruby on rails 如何使用冗余的'let!'干涸RSpec测试方法调用?,ruby-on-rails,rspec,dry,Ruby On Rails,Rspec,Dry,我如何在我的Rails应用程序中使用RSpec创建这样的测试块: describe "POST create" do describe "if we have a logged in user and he can be an owner" do describe "and if params are valid" do let!(:service_attributes_with_categories_1_and_2) { FactoryBot.attri
describe "POST create" do
describe "if we have a logged in user and he can be an owner" do
describe "and if params are valid" do
let!(:service_attributes_with_categories_1_and_2) {
FactoryBot.attributes_for :service_with_categories_1_and_2
}
let!(:category_1) { FactoryBot.create :category, {id: 1} }
let!(:category_2) { FactoryBot.create :category, {id: 2} }
it "creates a new service" do
# ...
end
it "creates associations with categories" do
# ...
end
end
describe "and if categories are not valid" do
# ...
end
describe "and if some common service params are not valid" do
# ...
end
end
describe "if no user is logged in, but params are valid" do
let!(:service_attributes_with_categories_1_and_2) {
FactoryBot.attributes_for :service_with_categories_1_and_2
}
let!(:category_1) { FactoryBot.create :category, {id: 1} }
let!(:category_2) { FactoryBot.create :category, {id: 2} }
it "doesn't create a new service" do
# ...
end
it "doesn't create associations with categories" do
# ...
end
end
describe "if logged user cannot be an owner, but params are valid" do
let!(:service_attributes_with_categories_1_and_2) {
FactoryBot.attributes_for :service_with_categories_1_and_2
}
let!(:category_1) { FactoryBot.create :category, {id: 1} }
let!(:category_2) { FactoryBot.create :category, {id: 2} }
it "doesn't create a new service" do
# ...
end
it "doesn't create associations with categories" do
# ...
end
end
end
正如我们所看到的,我有很多多余的
let代码>方法调用,但我不知道如何使其干燥。我不能只定义普通方法,因为在这种情况下,变量只在这个方法的作用域中可用。我也不能让我的类别在一般范围内创建,因为在两种情况下,由于测试的性质,它们不应该被创建。那么,从技术上讲,我应该如何做到这一点呢?最后我决定将FactoryBot.create
函数分为两个步骤:FactoryBot.build
和save
函数在获取的对象上运行。它允许我移动我的let代码>调用main作用域和define方法,该方法在需要的情况下准确地保存构建的对象。我的干式代码现在看起来是这样的:
describe "POST create" do
let!(:service_attributes_with_categories_1_and_2) {
FactoryBot.attributes_for :service_with_categories_1_and_2
}
let!(:category_1) { FactoryBot.build :category, {id: 1} }
let!(:category_2) { FactoryBot.build :category, {id: 2} }
def save_categories_1_and_2
category_1.save
category_2.save
end
describe "if we have a logged in user and he can be an owner" do
describe "and if params are valid" do
before(:each) do
save_categories_1_and_2
end
it "creates a new service" do
# ...
end
it "creates associations with categories" do
# ...
end
end
describe "and if categories are not valid" do
# ...
end
describe "and if some common service params are not valid" do
# ...
end
end
describe "if no user is logged in, but params are valid" do
before(:each) do
save_categories_1_and_2
end
it "doesn't create a new service" do
# ...
end
it "doesn't create associations with categories" do
# ...
end
end
describe "if logged user cannot be an owner, but params are valid" do
before(:each) do
save_categories_1_and_2
end
it "doesn't create a new service" do
# ...
end
it "doesn't create associations with categories" do
# ...
end
end
end
非常感谢@midlins和@Taryn East为我指明了正确的方向@Taryn East-您建议的调整也适用于上述案例,但在我的应用程序中,我还有更高级的案例,这还不够。我认为这里介绍的解决方案更具普遍性。您可以按如下方式使您的规格干燥:
1) 使用let
代替定义方法
2) 将您的上下文
块安排为便于适应进一步的情况
describe 'POST create' do
let!(:service_attributes_with_categories_1_and_2) {
FactoryBot.attributes_for :service_with_categories_1_and_2
}
let!(:category_1) { FactoryBot.build :category, {id: 1} }
let!(:category_2) { FactoryBot.build :category, {id: 2} }
let(:save_categories_1_and_2) { category_1.save && category_2.save }
context 'when user is logged in' do
context 'when user is an owner' do
context 'when params are valid' do
before do
save_categories_1_and_2
end
it 'creates a new service' do
end
it 'creates associations with categories' do
end
end
context 'when categories are not valid' do
end
context 'when some common service params are not valid' do
end
end
context 'when user is not an owner' do
context 'when params are valid' do
before do
save_categories_1_and_2
end
it "doesn't create a new service" do
end
it "doesn't create associations with categories" do
end
end
end
end
context 'when no user is logged in' do
context 'when params are valid' do
before do
save_categories_1_and_2
end
it "doesn't create a new service" do
end
it "doesn't create associations with categories" do
end
end
end
end
是否有任何理由说明在描述“后期创建”do
下的顶部范围内声明一次它们将不起作用?是的,这是因为在某些情况下,我不希望在数据库中创建类别。是否还有其他测试没有显示?根据您展示的内容,您有三个测试,每个测试设置相同的测试数据。你为什么不在做出断言之前设置一次呢?你错了。第一组let代码>调用在作用域“中定义,如果参数有效”
,而在作用域“中我们没有定义,如果类别无效”
和“如果一些公共服务参数无效”
。调整作用域,使前两个作用域是“如果参数有效”(在这里声明这些让
与“If参数无效”(如果参数无效),所有其他作用域都在这些范围内。