You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cucumber Ruby(Capybara)跨步骤共享实例变量问题:页面断言时@thing为nil报错

解决Cucumber+Ruby中@thing为nil的NoMethodError问题

Hey there! Let's break down why you're hitting that undefined method 'name' for nil:NilClass error and fix it step by step.

1. 核心问题:步骤定义的语法错误

The biggest culprit here is the syntax in your step definitions—you've got an extra space between the keyword (Given/And/When/Then) and the quoted step string. This breaks Cucumber's step matching, meaning your @thing instance variable never gets initialized in the first place.

错误写法

Given ("I am a user") do
  @user = FactoryBot.create(:user)
end
And ("I own a thing") do
  @thing = FactoryBot.create(:thing, user: @user)
end

正确写法

Remove the space between the keyword and the string (or skip the parentheses entirely, which is Cucumber's recommended style):

Given("I am a user") do
  @user = FactoryBot.create(:user)
end

And("I own a thing") do
  @thing = FactoryBot.create(:thing, user: @user)
end

# 或者更简洁的无括号写法
Given "I am a user" do
  @user = FactoryBot.create(:user)
end

And "I own a thing" do
  @thing = FactoryBot.create(:thing, user: @user)
end

2. 修复页面路由的逻辑

Your attempt to use visit (page_path($thing)) was off—global variables like $thing aren't the right approach here, and you're probably using the wrong route helper.

If you're trying to visit the detail page for your thing, use Rails' standard resource route helper (thing_path) instead of page_path:

When("I visit the page") do
  # 访问物品详情页
  visit thing_path(@thing)
  # 如果是用户的物品列表页,用这个:
  # visit user_things_path(@user)
end

Double-check your config/routes.rb to confirm the correct route helper for your page.

3. 验证变量共享与步骤执行

Cucumber shares instance variables (@user, @thing) across steps as long as the steps are matched correctly. To debug, add simple print statements to confirm variables are being created:

Given("I am a user") do
  @user = FactoryBot.create(:user)
  puts "Created user ID: #{@user.id}" # 调试用,确认用户创建成功
end

And("I own a thing") do
  @thing = FactoryBot.create(:thing, user: @user)
  puts "Created thing name: #{@thing.name}" # 调试用,确认物品创建成功
end

Then("I can see my thing") do
  puts "Thing name in final step: #{@thing&.name}" # 调试用,看变量是否存在
  expect(page).to have_text(@thing.name)
end

额外优化:更清晰的步骤设计

For better maintainability, make your feature steps more explicit and use parameterization to reuse code:

Feature文件优化

Feature: View Owned Things
  Given I am a registered user
  And I have created a thing named "My Custom Thing"
  When I visit my thing's detail page
  Then I should see the text "My Custom Thing"

对应的步骤定义

Given("I am a registered user") do
  @user = FactoryBot.create(:user)
end

Given("I have created a thing named {string}") do |thing_name|
  @thing = FactoryBot.create(:thing, user: @user, name: thing_name)
end

When("I visit my thing's detail page") do
  visit thing_path(@thing)
end

Then("I should see the text {string}") do |expected_text|
  expect(page).to have_text(expected_text)
end

内容的提问来源于stack exchange,提问作者cinameng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:17:28