Rspec, Rails: как протестировать приватные методы контроллеров? - PullRequest
122 голосов
/ 25 ноября 2010

У меня есть контроллер:

class AccountController < ApplicationController
  def index
  end

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

Как проверить приватный метод current_account с помощью rspec?

PS Я использую Rspec2 и Ruby on Rails 3

Ответы [ 10 ]

190 голосов
/ 25 ноября 2010

Использовать # 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
37 голосов
/ 28 мая 2012

Я использую метод отправки.Например:

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

Поскольку "send" может вызывать приватные методы

23 голосов
/ 25 ноября 2010

Где используется метод current_account?Для какой цели он служит?

Как правило, вы не тестируете приватные методы, а скорее тестируете методы, которые вызывают приватный.

8 голосов
/ 17 февраля 2017

Вы должны , а не проверять ваши личные методы напрямую, они могут и должны быть проверены косвенно, используя код из открытых методов.

Это позволяет вам изменить внутренние компоненты вашего кодадорога без необходимости менять свои тесты.

4 голосов
/ 29 июня 2014

Вы можете сделать свои закрытые или защищенные методы общедоступными:

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

Просто поместите этот код в свой класс тестирования, подставив вместо него имя класса.Включите пространство имен, если применимо.

3 голосов
/ 13 октября 2011
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
1 голос
/ 24 мая 2014

Используйте rspec-context-private-private * , чтобы временно сделать приватные методы общедоступными в контексте.

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
1 голос
/ 15 июня 2012

Модульное тестирование частных методов кажется слишком неконтролируемым с поведением приложения.

Вы сначала пишете свой код вызова?Этот код не вызывается в вашем примере.

Поведение таково: вы хотите, чтобы объект был загружен из другого объекта.

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

0 голосов
/ 06 декабря 2014

Я знаю, что это довольно странно, но работает, если вы хотите, чтобы методы тестировались с помощью 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 
0 голосов
/ 25 ноября 2010

Если вам нужно протестировать приватную функцию, создайте публичный метод, который вызывает приватную функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...