水豚功能测试 ActionView::Template::Error

Capybara feature test ActionView::Template::Error

使用 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

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

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

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

除此之外,你永远不应该对 Capybara 对象使用基本的 RSpec 匹配器(eq 等),而应该使用 Capybara 提供的匹配器来处理通过提供 waiting/retrying 行为使用浏览器进行测试。所以而不是

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

你应该有类似的东西

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

找出问题发生的原因。

忘了类别模型中的方法,它确保只有顶级类别显示在首页上。

  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