[英]How to DRY up RSpec tests shared by different actions in same controller
[英]How to DRY up RSpec tests with redundant `let!` method calling?
我如何使用RSpec在我的Rails应用程序中进行这样的测试:
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!
方法调用,但我不知道如何使其变干。 我不能只定义普通方法,因为在这种情况下,变量仅在此方法的范围内可用。 我也不能让我的类别在一般范围内创建,因为在两种情况下,由于测试的性质,不应创建类别。 那么,从技术上我该怎么做呢?
您可以按以下方式使您的规格变干:
1)使用let
代替定义方法。
2)安排您的context
块,以便可以轻松容纳更多情况。
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
最后,我决定将FactoryBot.create
函数分为两个步骤: FactoryBot.build
和.save
函数在获得的对象上运行。 它让我动容了let!
调用主作用域,并定义方法,在需要的情况下,此方法可以完全保存构建的对象。 我的DRY代码现在看起来像这样:
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-您建议的调整方式也适用于此处所述的情况,但是在我的应用中,我还拥有更高级的情况,这还不够。 我认为这里介绍的解决方案更具通用性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.