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

时间:2010-11-24 21:26:51

标签: ruby-on-rails rspec

我有控制器:

class AccountController < ApplicationController
  def index
  end

  private
  def current_account
    @current_account ||= current_user.account
  end
end

如何使用rspec测试私有方法current_account

P.S。我使用Rspec2和Ruby on Rails 3

10 个答案:

答案 0 :(得分:190)

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

答案 1 :(得分:37)

我使用send方法。例如:

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

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

答案 2 :(得分:23)

使用current_account方法在哪里?它有什么用途?

通常,您不测试私有方法,而是测试调用私有方法的方法。

答案 3 :(得分:8)

你应该直接测试你的私人方法,他们可以而且应该通过运用公共方法的代码间接测试。

这使您可以在不改变测试的情况下更改代码的内部结构。

答案 4 :(得分:4)

您可以将私有或受保护的方法设为public:

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

只需将此代码放在测试类中,替换您的类名。如果适用,请包括命名空间。

答案 5 :(得分:3)

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

答案 6 :(得分:1)

如果需要测试私有函数,请创建一个调用私有函数的公共方法。

答案 7 :(得分:1)

单元测试私有方法似乎与应用程序的行为脱节。

您是在先编写您的主叫代码吗? 在您的示例中不会调用此代码。

行为是:您希望从另一个对象加载对象。

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

答案 8 :(得分:1)

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

答案 9 :(得分:0)

我知道这有点像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