使用 Let 构建模型的多个实例
Using Let to build multiple instances of a model
我正尝试 运行 在 will_paginate 上进行测试。我知道它在技术上是可行的,但由于我无法创建多条记录,我无法使规范生效。我在 Rails 上使用 Capybara 和 Rspec 以及 Ruby。
这是我的功能规范中的内容。
RSpec.describe "Users Index", type: :feature do
describe "Pagination" do
let(:valid_user) { create(:user, name: "Mogli") }
let(:other_user) { create(:user, 50) }
it "successfully paginates" do
log_in_as_feature(valid_user)
visit users_path
puts URI.parse(current_url)
expect(page).to have_css('div.pagination')
expect(page).to have_link(href: user_path(valid_user), text: valid_user.name)
first_page_of_users = User.paginate(page: 1)
first_page_of_users.each do |user|
expect(page).to have_link(href: user_path(user), text: user.name)
unless user == valid_user
expect(page).to have_link(href: user_path(user), text: "delete")
end
end
end
end
结束
我的工厂很简单:
FactoryGirl.define do
sequence(:name) { |n| "Person#{n}" }
factory :user do
name
email { "#{name}@example.com" }
password "foobar"
password_confirmation "foobar"
activated true
activated_at Time.zone.now
end
end
我的第四行是罪魁祸首。它实际上并没有建立用户。我尝试使用 FactoryGirl.create(:user, 50)
,但最终全面破坏了 27 个测试,我不得不重置测试数据库。
我不知道还有什么方法可以一次创建多个虚拟用户,同时始终将 Mogli 保持为第一个。任何见解表示赞赏。
编辑:如果我评论了 have_css 测试,那么我的测试通过了。
这里是 div
的错误
1) Users Index Pagination successfully paginates
Failure/Error: expect(page).to have_css('div.pagination')
expected to find css "div.pagination" but there were no matches
# ./spec/features/users_index_spec.rb:13:in
块(3 级)在'
在 0.82368 秒内完成(文件加载时间为 2.17 秒)`
编辑:添加我的局部视图和 index.html.erb 视图。
我的视图只呈现@users 部分
即:
1 <li>
2 <%= gravatar_for user, size: 50 %>
3 <%= link_to user.name, user %>
4 <% if current_user.admin? && !current_user?(user) %>
5 | <%= link_to "delete", user, method: :delete,
6 data: { confirm: "You sure?" } %>
7 <% end %>
8
9 </li>
首先,let
是lazy-evaluated。这意味着直到您在规范中调用它时才会对其进行评估。您没有在规范中使用 other_user
,因此未对其进行评估。
其次,如果您想创建一个包含 50 个用户的列表来设置您的规范,请使用 before
块:
before do
# using create_list
create_list(:user, 50)
# OR just
50.times { create(:user) }
end
it "successfully paginates" do
# ...
end
正如 Jan 已经提到的,let
是延迟求值的。如果你不使用 other_user
,它永远不会被创建。不过,有一个热切的对手。
let!(:other_user) { create(:user, 50) }
这个总是创建的。
您的示例存在一些问题。正如其他人所提到的 let
是延迟评估的,因此要创建不直接引用的对象,您需要使用 let!
。此外,FactoryGirl 的 create
不需要生成很多记录,为此你需要 create_list
。最后,Capybara 的 have_link
将您要查找的 link 的文本作为第一个参数,因此无需传递 :text
选项
RSpec.describe "Users Index", type: :feature do
describe "Pagination" do
let!(:valid_user) { create(:user, name: "Mogli") }
let!(:other_users) { create_list(:user, 50) }
it "successfully paginates" do
log_in_as_feature(valid_user)
visit users_path
puts URI.parse(current_url)
expect(page).to have_css('div.pagination')
expect(page).to have_link(valid_user.name, href: user_path(valid_user))
User.paginate(page: 1).each do |user|
expect(page).to have_link(user.name, href: user_path(user))
expect(page).to have_link("delete", href: user_path(user)) unless user == valid_user
end
end
end
我正尝试 运行 在 will_paginate 上进行测试。我知道它在技术上是可行的,但由于我无法创建多条记录,我无法使规范生效。我在 Rails 上使用 Capybara 和 Rspec 以及 Ruby。
这是我的功能规范中的内容。
RSpec.describe "Users Index", type: :feature do
describe "Pagination" do
let(:valid_user) { create(:user, name: "Mogli") }
let(:other_user) { create(:user, 50) }
it "successfully paginates" do
log_in_as_feature(valid_user)
visit users_path
puts URI.parse(current_url)
expect(page).to have_css('div.pagination')
expect(page).to have_link(href: user_path(valid_user), text: valid_user.name)
first_page_of_users = User.paginate(page: 1)
first_page_of_users.each do |user|
expect(page).to have_link(href: user_path(user), text: user.name)
unless user == valid_user
expect(page).to have_link(href: user_path(user), text: "delete")
end
end
end
end
结束
我的工厂很简单:
FactoryGirl.define do
sequence(:name) { |n| "Person#{n}" }
factory :user do
name
email { "#{name}@example.com" }
password "foobar"
password_confirmation "foobar"
activated true
activated_at Time.zone.now
end
end
我的第四行是罪魁祸首。它实际上并没有建立用户。我尝试使用 FactoryGirl.create(:user, 50)
,但最终全面破坏了 27 个测试,我不得不重置测试数据库。
我不知道还有什么方法可以一次创建多个虚拟用户,同时始终将 Mogli 保持为第一个。任何见解表示赞赏。
编辑:如果我评论了 have_css 测试,那么我的测试通过了。
这里是 div
的错误1) Users Index Pagination successfully paginates
Failure/Error: expect(page).to have_css('div.pagination')
expected to find css "div.pagination" but there were no matches
# ./spec/features/users_index_spec.rb:13:in
块(3 级)在'
在 0.82368 秒内完成(文件加载时间为 2.17 秒)`
编辑:添加我的局部视图和 index.html.erb 视图。
我的视图只呈现@users 部分
即:
1 <li>
2 <%= gravatar_for user, size: 50 %>
3 <%= link_to user.name, user %>
4 <% if current_user.admin? && !current_user?(user) %>
5 | <%= link_to "delete", user, method: :delete,
6 data: { confirm: "You sure?" } %>
7 <% end %>
8
9 </li>
首先,let
是lazy-evaluated。这意味着直到您在规范中调用它时才会对其进行评估。您没有在规范中使用 other_user
,因此未对其进行评估。
其次,如果您想创建一个包含 50 个用户的列表来设置您的规范,请使用 before
块:
before do
# using create_list
create_list(:user, 50)
# OR just
50.times { create(:user) }
end
it "successfully paginates" do
# ...
end
正如 Jan 已经提到的,let
是延迟求值的。如果你不使用 other_user
,它永远不会被创建。不过,有一个热切的对手。
let!(:other_user) { create(:user, 50) }
这个总是创建的。
您的示例存在一些问题。正如其他人所提到的 let
是延迟评估的,因此要创建不直接引用的对象,您需要使用 let!
。此外,FactoryGirl 的 create
不需要生成很多记录,为此你需要 create_list
。最后,Capybara 的 have_link
将您要查找的 link 的文本作为第一个参数,因此无需传递 :text
选项
RSpec.describe "Users Index", type: :feature do
describe "Pagination" do
let!(:valid_user) { create(:user, name: "Mogli") }
let!(:other_users) { create_list(:user, 50) }
it "successfully paginates" do
log_in_as_feature(valid_user)
visit users_path
puts URI.parse(current_url)
expect(page).to have_css('div.pagination')
expect(page).to have_link(valid_user.name, href: user_path(valid_user))
User.paginate(page: 1).each do |user|
expect(page).to have_link(user.name, href: user_path(user))
expect(page).to have_link("delete", href: user_path(user)) unless user == valid_user
end
end
end