Rspec,Rails:如何testing控制器的私有方法?

我有控制器:

class AccountController < ApplicationController def index end private def current_account @current_account ||= current_user.account end end 

如何用rspectesting私有方法current_account

PS我使用Rspec2和Ruby on Rails 3

使用#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 

我使用发送方法。 例如:

 event.send(:private_method).should == 2 

因为“发送”可以调用私人方法

在哪里使用current_account方法? 它的目的是什么?

通常,您不要testing私有方法,而是testing调用私有方法的方法。

你可以让你的私人或受保护的方法公开:

 MyClass.send(:public, *MyClass.protected_instance_methods) MyClass.send(:public, *MyClass.private_instance_methods) 

只要把这个代码放在你的testing类中,代替你的类名。 包括命名空间(如果适用)。

你不应该直接testing你的私有方法,他们可以而且应该通过公共方法来运行代码来间接地进行testing。

这使您可以在路上更改代码的内部,而无需更改testing。

 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 

unit testing私有方法似乎太不符合应用程序的行为。

你是先写你的电话号码吗? 这个代码在你的例子中没有被调用。

行为是:你想从另一个对象加载一个对象。

 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 

为什么你想从你应该试图描述的行为中脱离出上下文来编写testing呢?

这个代码在很多地方使用吗? 需要一个更通用的方法?

https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/controller-specs/anonymous-controller

使用rspec-context-private gem暂时在上下文中公开私有方法。

 gem 'rspec-context-private' 

它通过向您的项目添加共享上下文来工作。

 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 

然后,如果将:private作为元数据传递给describe块,则私有方法将在该上下文中公开。

 describe AccountController, :private do it 'can test private methods' do expect{subject.current_account}.not_to raise_error end end 

如果您需要testing私有函数,请创build一个调用私有函数的公共方法。

我知道这是有点hacky,但它的作品,如果你想方法rspec可testing,但在产品中不可见。

 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 

现在,当你运行你的规格是这样的:

 RAILS_ENV=test bundle exec rspec spec/foo_spec.rb