在RSpec和Capybara功能规范中伪造实例变量

3

我想在重构公司的一些旧代码之前设置一些功能规格。这是一个有点不寻常的设置,但我能够了解到关于测试替身的足够信息来绕过认证并开始工作。我仍然遇到一个问题是,我绕过的这些方法中设置的某些实例变量会被视图使用,所以我得到了“undefined method for nil:NilClass”错误。我想在对程序代码进行任何更改之前运行规格,但在本例中,我可以轻松地将特定的实例变量移动到另一个方法中。但我相信会出现更多类似的情况。以下是我目前正在处理的示例:

def security_level
  @right_now = Time.now

  #
  # other code that wont work without
  # connecting to a remote authentication
  # server
  #

end

然后在我的规格中:

feature 'Navigation' do
  before(:each) do
    allow_any_instance_of(ApplicationController).to receive(:security_level).and_return(nil)
  end
  scenario 'is possible' do
    visit root_path
    expect(page.has_content?('Quick Stats'))
  end
end

这里有一个错误,源于视图中的@right_now.year
 Failure/Error: visit root_path
 NoMethodError:
   undefined method `year' for nil:NilClass
 # ./common/views/layouts/bootstrap/layout.haml:63

编辑: 是否有一种方法可以在功能规格说明中从控制器中设置实例变量?


1
let 关键字/方法。 - Petr Skocik
除了使用let关键字,我认为你想要返回一个时间而不是nil。 - ruby_newbie
2个回答

4

想要实现您想要的目标并不容易。

feature规范主要由Capybara处理,而不是RSpec。 Capybara在外部进程中运行大部分浏览器/ rails服务器行为。这使得它从RSpec的角度来看无法访问。因此,您不能以这种方式使用存根/双倍。

Feature规范在很大程度上意味着端到端接受测试。其想法是像使用您的系统的人一样操作您的系统。通常,在这些类型的规范中,您执行各种“工作流”。这意味着,具有规范,登录用户,导航到特定页面,填写表单,单击按钮和链接。然后,您通常对视图中看到的内容进行期望。

这意味着您的规范将更像:

feature 'Navigation' do
  let(:regular_user) { User.create!(name: 'A Regular User') }

  def sign_in(a_user)
    visit sign_in_url
    # fill out form
    click_button 'Sign In'
  end

  before(:each) do
    sign_in(regular_user)
  end

  scenario 'is possible' do
    visit root_path
    expect(page.has_content?('Quick Stats'))
  end
end

这正是我担心的。它使用一些遗留代码来连接LDAP服务器,这些代码在多个应用程序之间共享。我能够设置一个单独的项目,可以像您在这里建议的那样完成完整的登录过程,但这需要将我的LDAP凭据保存在文件中。现在回到单元测试。 - Shaun
不了解代码的情况下很难提出建议。即使是遗留代码,如果这部分相对独立,可能可以插入一个虚假服务。您可能需要在测试环境配置或初始化器中进行此操作。 - Aaron K

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接