Подтвердить что ты не робот

Rspec, Rails: как тестировать частные методы контроллеров?

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

class AccountController < ApplicationController
  def index
  end

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

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

P.S. Я использую Rspec2 и Ruby on Rails 3

4b9b3361

Ответ 1

Используйте #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

Ответ 2

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

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

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

Ответ 3

Где используется метод current_account? Какую цель он выполняет?

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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

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

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

Ответ 9

Используйте 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

Ответ 10

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