【问题标题】:Capybara feature test ActionView::Template::ErrorCapybara 功能测试 ActionView::Template::Error
【发布时间】:2020-07-13 09:38:56
【问题描述】:

使用 Rspec 和 Capybara 进行功能测试。不幸的是,我遇到了问题...

basic_interaction_spec.rb

RSpec.describe "basic interaction" do 
    before :each do
        category = build_stubbed(:category, name: "Pants")
    end
    
    it "displays category" do
        visit("/")
        click_link("Pants")
        expect(current_path).to eq("pants")
        expect(page).to have_title("Pants | app_name")
    end
end

结果

Failure/Error: <li><%= link_to category.name, products_path(category_or_product: category.slug) %></li>
     
     ActionView::Template::Error:
       undefined method `name' for nil:NilClass

homepage_controller.rb

def index
    @categories = []
    Category.root_order.each do |category_name|
      @categories << Category.find_by(name: category_name)
end

你们能看出我哪里出错了吗?

【问题讨论】:

    标签: ruby-on-rails rspec capybara


    【解决方案1】:

    在编写功能规范时,您不能将build_stubbed 用于您希望您的应用能够访问的记录。假设您在 before 块中构建的 category 是您希望应用程序在页面上显示的内容,那么您需要实际创建记录,因为应用程序正在通过数据库查询访问它。

    before :each do
        category = create(:category, name: "Pants")
    end
    

    除此之外,您永远不应该将基本的 RSpec 匹配器(eq 等)与 Capybara 对象一起使用,而应该使用 Capybara 提供的匹配器,它通过提供等待 /重试行为。所以不是

    expect(current_path).to eq("pants")
    

    你应该有类似的东西

    expect(page).to have_current_path("pants")
    

    【讨论】:

    • 我明白了。我已更改 build_stubbed 以创建 RSpec 匹配器并将其替换为 Capybara 匹配器,但仍然存在相同的错误。
    • @JonasFagerlund 那么您的应用程序中有错误。您认为“类别”为 nil,但您没有显示足够的信息来查看它的实际来源
    • 你是对的!找出问题并将其总结为答案。
    【解决方案2】:

    找出问题发生的原因。

    忘记了类别模型中确保主页上只显示顶级类别的方法。

      def self.root_order
        %w[Tops Outerwear Pants Suits Shoes]
      end
    

    当没有创建所有顶级类别时,这会导致问题。使用以下夹具,测试通过。

        before :each do
          category1 = create(:category, name: "Tops")
          category2 = create(:category, name: "Outerwear")
          category3 = create(:category, name: "Pants")
          category4 = create(:category, name: "Suits")
          category5 = create(:category, name: "Shoes")
        end
    

    【讨论】:

    • 因为您不需要在测试场景中实际访问 category1..5,只需执行 %w[Tops Outerwear Pants Suits Shoes].each { |n| create(:category, name: n) } 之类的操作,而不是创建 5 个未使用的变量并重复代码 - 或者更好的是为您的数据库设置种子如果这些类别总是需要在那里
    • 听起来是个好主意!将在数据库中播种。
    猜你喜欢
    • 2023-03-22
    • 2017-08-28
    • 2015-04-15
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多