簡體   English   中英

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

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM