【问题标题】:Using Let to build multiple instances of a model使用 Let 构建模型的多个实例
【发布时间】:2023-04-06 19:50:02
【问题描述】:

我正在尝试对 will_paginate 进行测试。我知道它在技术上是可行的,但由于我无法创建多个记录,我无法让规范正常工作。我在 Ruby on Rails 上使用 Capybara 和 Rspec。

这是我的功能规范中的内容。

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:inblock (3 个级别) in '

在 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(:other_user) { create(:user, 50) } 应该像let(:other_user) { create(:user, name: 'another name') }`
  • 您刚刚在问题中更新的错误意味着 div 在页面上不可见。查看page.html 并查看页面上的实际内容。

标签: ruby-on-rails ruby rspec capybara factory-bot


【解决方案1】:

您的示例存在一些问题。正如其他人提到的let 被延迟评估,因此要创建不直接引用的对象,您需要使用let!。此外,FactoryGirl 的create 不需要制作大量记录,您需要create_list。最后,Capybara 的have_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

【讨论】:

  • 谢谢,我没有意识到 Capybara 是这样工作的。我也试过让!我的第一个让选项下的选项,虽然它有效,但它在此过程中丢失了我的有效用户名。 “用户索引分页成功分页失败/错误:expect(page).to have_link(valid_user.name, href: user_path(valid_user)) 预期找到链接“Mogli”但没有匹配项# ./spec/features/users_index_spec。 rb:16:in `block (3 levels) in '"
  • @user12398736 这往往意味着该链接实际上不在页面上。您确定 valid_user 实际上在第一个分页页面上吗?由于在调用valid_user 之前不会评估let(:valid_user 块,因此它可能会在第二页上。要解决此问题,您必须在两种情况下都使用 let! - 答案已更新
  • 我认为应该如此。我的 index.html.erb: 1 2

    All Users

    3 4 5
      6 7
    8 and my partial 1
  • 2 3 4 5 | 7 8 9
  • 哪些在哪个页面上取决于返回记录的排序顺序。通过将第一个 let 更改为 let! ,它将在 other_users 之前创建 valid_user - 因此您需要确保 @users 按 id 或 created_at 日期对记录进行排序
  • 按id排序。 @user = User.find(params[:id]) 也许我应该重置测试数据库并重做?那将改变创造的顺序。 -edit:修复了 valid_user 错误,但删除了“删除”选项。我给了 valid_user 管理员权限,现在所有测试都通过了。非常感谢。
  • 【解决方案2】:

    首先,letlazy-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
    

    【讨论】:

    • 当我使用 before 时,我将除分页之外的其他测试注释掉,然后它通过了。一旦我使所有测试都处于活动状态,它就会失败并显示“用户索引分页成功分页失败/错误:expect(page).to have_link(valid_user.name, href:user_path(valid_user)) 预计会找到链接“Mogli”但有没有匹配 # ./spec/features/users_index_spec.rb:16:in `block (3 levels) in '"
    【解决方案3】:

    正如 Jan 已经提到的,let 是惰性求值的。如果你不使用other_user,它将永远不会被创建。不过,有一个热切的对手。

    let!(:other_user) { create(:user, 50) }
    

    这个总是被创建的。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签