[英]Rspec, Rails: how to test private methods of controllers?
我有控制器:
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
我用send方法。 例如:
event.send(:private_method).should == 2
因為“發送”可以調用私有方法
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
如果需要測試私有函數,請創建一個調用私有函數的公共方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.