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

我有控制器:

class AccountController < ApplicationController
def index
end


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

如何用 rspec 测试私有方法 current_account

另外,我在 Rails 3中使用 Rspec2和 Ruby

62209 次浏览

Current _ account 方法在哪里被使用? 它的作用是什么?

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

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

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

我使用发送方法。例如:

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

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

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

你是先写呼叫代码吗? 在您的示例中不调用此代码。

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

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

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

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

只需将此代码置于测试类中,替换类名即可。如果适用,请包括命名空间。

我知道这有点古怪,但是如果您希望方法可以通过 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

您应该直接使用 没有测试您的私有方法,它们可以而且应该通过使用来自公共方法的代码间接地进行测试。

这允许您在以后更改代码的内部结构,而不必更改测试。