繁体   English   中英

如何测试 controller 中的实例变量?

[英]How do I test an instance variable in a controller?

我的几个导师告诉我使用 controller 规范测试一段代码,即使某些请求规范正在测试内容。 我想知道是否可以在 rspec controller 测试中测试像@user这样的实例变量是否可以设置为someObjectnil

到目前为止,我已经尝试了几种不同的方法来测试它,但我在 rspec 测试方面的技能至少可以说是初级的。 我尝试的第一件事是 mocking 输出 current_user 和 'User.get_from_auth_user(current_user)。 模拟的 object 打印良好并输出。 问题是......我希望能够说类似expect(@user).to equal(mockedUser)但这似乎永远不会奏效。 我总是得到类似的东西:

Expect does not equal received
expected is nil
received is { someMockedObject }

这是我要测试的代码。

class ApplicationController < ActionController::Base
  before_action :set_user

  def set_user
    return if current_user.nil?

    @user = User.get_from_auth_user(current_user)
  end
end

我想知道我是否走在正确的道路上,或者什么是完全测试这段代码的更好选择。 我觉得答案应该很简单。

你的导师很愚蠢。 虽然了解 controller 规范可能会很好,因为它们在旧应用程序中无处不在,但将它们添加到新应用程序并不是一个好习惯。

对于新的 Rails 应用程序:我们不建议将 rails-controller-testing gem 添加到您的应用程序中。 Rails 团队和 RSpec 核心团队的官方建议是改为编写请求规范。 请求规范允许您专注于单个 controller 操作,但与 controller 不同的是,测试涉及路由器、中间件堆栈以及机架请求和响应。 这增加了您正在编写的测试的真实性,并有助于避免 controller 规范中常见的许多问题。

DHH 很好地解释了测试 controller 的实例变量有什么问题以及您应该做什么:

测试您的 controller 设置了哪些实例变量是一个坏主意。 这严重超出了测试应该知道的范围。 您可以测试设置了什么 cookies,返回什么 HTTP 代码,视图的外观,或者数据库发生了什么突变,但是测试 controller 的内部结构并不是一个好主意。

这就是为什么assigns提取到单独的 gem 的原因。 这一切都归结为测试你的代码做了什么——而不是它是怎么做的。

看:

使用 assigns assigns(:user)获取实例变量@user 在您的规范中, @user是该测试上下文中的一个变量,它与@user中的 @user 不同。

https://relishapp.com/rspec/rspec-rails/docs/controller-specs

除了@chans@arieljuod 的答案,值得一提的是,为了在您的规范中使用assigns ,您需要设置rails-controller-testing gem,因为从 Rails 5 开始不推荐使用assigns

# File actionpack/lib/action_dispatch/testing/test_process.rb, line 6
def assigns(key = nil)
  raise NoMethodError,
    "assigns has been extracted to a gem. To continue using it,
    add `gem 'rails-controller-testing'` to your Gemfile."
end

controller 测试用例如下所示

describe 'GET #set_user' do
  let!(:mock_user) { 
      @mockuserObj = { id: 1, name: "username" }
  }
  before(:each) do
    controller.instance_variable_set(:current_user, @mockuserObj)
    get :set_user
  end
  context 'when current_user is present' do
    it "sets the current user" do
      expect(assigns(:user)).to eq(@mockuserObj)
    end
  end
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM