我有控制器:
class AccountController < ApplicationController
def index
end
private
def current_account
@current_account ||= current_user.account
end
end
如何使用 rspec 测试私有方法 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
因为“发送”可以调用私有方法
.send
测试私有方法中的实例变量?
current_account 方法在哪里使用?它的用途是什么?
通常,您不测试私有方法,而是测试调用私有方法的方法。
您不应该直接测试您的私有方法,它们可以而且应该通过执行来自公共方法的代码来间接测试。
这使您可以在不更改测试的情况下更改代码的内部结构。
您可以将私有或受保护的方法设为公开:
MyClass.send(:public, *MyClass.protected_instance_methods)
MyClass.send(:public, *MyClass.private_instance_methods)
只需将此代码放在您的测试类中替换您的类名即可。如果适用,包括命名空间。
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
单元测试私有方法似乎与应用程序的行为脱节。
你是先写你的调用代码吗?您的示例中未调用此代码。
行为是:您希望从另一个对象加载一个对象。
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
为什么你想从你应该试图描述的行为中脱离上下文来编写测试?
此代码是否在很多地方使用?需要更通用的方法?
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
我知道这有点 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
现在,当您可以运行时,您的规格如下:
RAILS_ENV=test bundle exec rspec spec/foo_spec.rb
如果您需要测试私有函数,请创建一个调用私有函数的公共方法。
不定期副业成功案例分享