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