Ruby-on-rails Rspec,Rails:如何测试控制器的私有方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4271696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rspec, Rails: how to test private methods of controllers?
提问by petRUShka
I have controller:
我有控制器:
class AccountController < ApplicationController
def index
end
private
def current_account
@current_account ||= current_user.account
end
end
How to test private method current_accountwith rspec?
如何current_account使用 rspec测试私有方法?
P.S. I use Rspec2 and Ruby on Rails 3
PS 我使用 Rspec2 和 Ruby on Rails 3
回答by monocle
Use #instance_eval
使用#instance_eval
@controller = AccountController.new
@controller.instance_eval{ current_account } # invoke the private method
@controller.instance_eval{ @current_account }.should eql ... # check the value of the instance variable
回答by graffzon
I use send method. Eg:
我使用发送方法。例如:
event.send(:private_method).should == 2
Because "send" can call private methods
因为“发送”可以调用私有方法
回答by Ryan Bigg
Where is the current_account method being used? What purpose does it serve?
current_account 方法在哪里使用?它的目的是什么?
Generally, you don't test private methods but rather test the methods that call the private one.
通常,您不测试私有方法,而是测试调用私有方法的方法。
回答by Lorem Ipsum Dolor
You should nottest your private methods directly, they can and should be tested indirectly by exercising the code from public methods.
你应该没有直接测试你的私有方法,他们能够而且应该通过公共方法行使代码间接测试。
This allows you to change the internals of your code down the road without having to change your tests.
这使您可以随时更改代码的内部结构,而无需更改测试。
回答by zishe
You could make you private or protected methods as public:
您可以将私有或受保护的方法设为公有:
MyClass.send(:public, *MyClass.protected_instance_methods)
MyClass.send(:public, *MyClass.private_instance_methods)
Just place this code in your testing class substituting your class name. Include the namespace if applicable.
只需将此代码放在您的测试类中,替换您的类名。如果适用,请包括命名空间。
回答by speedingdeer
require 'spec_helper'
describe AdminsController do
it "-current_account should return correct value" do
class AccountController
def test_current_account
current_account
end
end
account_constroller = AccountController.new
account_controller.test_current_account.should be_correct
end
end
回答by Brent Greeff
Unit testing private methods seems too out of context with the behaviour of the application.
单元测试私有方法似乎与应用程序的行为脱节。
Are you writing your calling code first? This code is not called in your example.
您是先编写调用代码吗?您的示例中未调用此代码。
The behaviour is: you want an object loaded from another object.
行为是:您希望从另一个对象加载一个对象。
context "When I am logged in"
let(:user) { create(:user) }
before { login_as user }
context "with an account"
let(:account) { create(:account) }
before { user.update_attribute :account_id, account.id }
context "viewing the list of accounts" do
before { get :index }
it "should load the current users account" do
assigns(:current_account).should == account
end
end
end
end
Why do u want to write the test out of context from the behaviour you should be trying to describe?
为什么您要根据您应该尝试描述的行为来编写测试?
Does this code get used in a lot of places? Need a more generic approach?
这段代码是否在很多地方使用?需要更通用的方法吗?
https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/controller-specs/anonymous-controller
https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/controller-specs/anonymous-controller
回答by barelyknown
Use the rspec-context-private gemto temporarily make private methods public within a context.
使用rspec-context-private gem在上下文中临时公开私有方法。
gem 'rspec-context-private'
It works by adding a shared context to your project.
它的工作原理是向您的项目添加共享上下文。
RSpec.shared_context 'private', private: true do
before :all do
described_class.class_eval do
@original_private_instance_methods = private_instance_methods
public *@original_private_instance_methods
end
end
after :all do
described_class.class_eval do
private *@original_private_instance_methods
end
end
end
Then, if you pass :privateas metadata to a describeblock, the private methods will be public within that context.
然后,如果您将:private元数据作为元数据传递给describe块,则私有方法将在该上下文中公开。
describe AccountController, :private do
it 'can test private methods' do
expect{subject.current_account}.not_to raise_error
end
end
回答by onetwopunch
I know this is kinda hacky, but it works if you want the methods testable by rspec but not visible in prod.
我知道这有点 hacky,但是如果您希望 rspec 可测试但在 prod 中不可见的方法,它会起作用。
class Foo
def public_method
#some stuff
end
eval('private') unless Rails.env == 'test'
def testable_private_method
# You can test me if you set RAILS_ENV=test
end
end
Now when you can run you're spec like so:
现在,当您可以运行时,您的规格如下:
RAILS_ENV=test bundle exec rspec spec/foo_spec.rb
回答by liamfriel
If you need to test a private function create a public method that invokes the private one.
如果您需要测试私有函数,请创建一个调用私有函数的公共方法。

