[英]How do I test an instance variable in a controller?
A couple of my mentors have told me to test a piece of code with controller spec even though the contents are being tested by some request specs.我的几个导师告诉我使用 controller 规范测试一段代码,即使某些请求规范正在测试内容。 I am wondering if I can test whether an instance variable like @user
can be set to someObject
or nil
from within an rspec controller test?我想知道是否可以在 rspec controller 测试中测试像@user
这样的实例变量是否可以设置为someObject
或nil
?
I've tried a couple different ways to test this so far, but my skills regarding rspec testing are to say the least, elementary.到目前为止,我已经尝试了几种不同的方法来测试它,但我在 rspec 测试方面的技能至少可以说是初级的。 The first thing I tried was mocking out the current_user and the 'User.get_from_auth_user(current_user).我尝试的第一件事是 mocking 输出 current_user 和 'User.get_from_auth_user(current_user)。 The mocked object prints fine and outputs.模拟的 object 打印良好并输出。 The problem is... I want to be able to say something like expect(@user).to equal(mockedUser)
but this never seems to work.问题是......我希望能够说类似expect(@user).to equal(mockedUser)
但这似乎永远不会奏效。 I always get something like:我总是得到类似的东西:
Expect does not equal received
expected is nil
received is { someMockedObject }
Here is the code I want to test.这是我要测试的代码。
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
I want to know if I'm going down the right path or what would be the better alternative to fully test this chunk of code.我想知道我是否走在正确的道路上,或者什么是完全测试这段代码的更好选择。 I feel like the answer should be a simple one.我觉得答案应该很简单。
Your mentors are being stupid.你的导师很愚蠢。 While it can be good to understand controller specs as they are everywhere in legacy applications adding them to new applications is not a good practice.虽然了解 controller 规范可能会很好,因为它们在旧应用程序中无处不在,但将它们添加到新应用程序并不是一个好习惯。
For new Rails apps: we don't recommend adding the rails-controller-testing gem to your application.对于新的 Rails 应用程序:我们不建议将 rails-controller-testing gem 添加到您的应用程序中。 The official recommendation of the Rails team and the RSpec core team is to write request specs instead. Rails 团队和 RSpec 核心团队的官方建议是改为编写请求规范。 Request specs allow you to focus on a single controller action, but unlike controller tests involve the router, the middleware stack, and both rack requests and responses.请求规范允许您专注于单个 controller 操作,但与 controller 不同的是,测试涉及路由器、中间件堆栈以及机架请求和响应。 This adds realism to the test that you are writing, and helps avoid many of the issues that are common in controller specs.这增加了您正在编写的测试的真实性,并有助于避免 controller 规范中常见的许多问题。
DHH explains pretty well what is wrong with testing the instance variables of your controller and what you should be doing instead: DHH 很好地解释了测试 controller 的实例变量有什么问题以及您应该做什么:
Testing what instance variables are set by your controller is a bad idea.测试您的 controller 设置了哪些实例变量是一个坏主意。 That's grossly overstepping the boundaries of what the test should know about.这严重超出了测试应该知道的范围。 You can test what cookies are set, what HTTP code is returned, how the view looks, or what mutations happened to the DB, but testing the innards of the controller is just not a good idea.您可以测试设置了什么 cookies,返回什么 HTTP 代码,视图的外观,或者数据库发生了什么突变,但是测试 controller 的内部结构并不是一个好主意。
Which is why assigns
was extracted to a separate gem.这就是为什么assigns
提取到单独的 gem 的原因。 It all boils down to testing what your code does - not how it does it.这一切都归结为测试你的代码做了什么——而不是它是怎么做的。
See:看:
Use assigns(:user)
to get the instance variable @user
.使用 assigns assigns(:user)
获取实例变量@user
。 In your spec, @user
is a variable on that test context, it's not the same @user
from the controller.在您的规范中, @user
是该测试上下文中的一个变量,它与@user
中的 @user 不同。
https://relishapp.com/rspec/rspec-rails/docs/controller-specs https://relishapp.com/rspec/rspec-rails/docs/controller-specs
In addition to @chans and @arieljuod answers, it worth to mention in order to use assigns
in your specs, you need to set up rails-controller-testing
gem, because assigns
is deprecated starting from Rails 5.除了@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
The controller test case looks like this 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.