Rspec, Rails: ¿cómo probar métodos privados de controladores?
Tengo controlador:
class AccountController < ApplicationController
def index
end
private
def current_account
@current_account ||= current_user.account
end
end
¿Cómo probar el método privado current_account
con rspec?
P.d. Yo uso Rspec2 y Ruby on Rails 3
10 answers
Use # 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-24 21:48:40
Uso el método send. Eg:
event.send(:private_method).should == 2
Porque "send" puede llamar a métodos privados
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-28 23:19:29
¿Dónde se utiliza el método current_account? Para qué sirve?
Generalmente, no se prueban métodos privados, sino que se prueban los métodos que llaman al privado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-24 21:29:57
Debe no probar sus métodos privados directamente, pueden y deben probarse indirectamente mediante el ejercicio del código de métodos públicos.
Esto le permite cambiar el funcionamiento interno de su código en el futuro sin tener que cambiar sus pruebas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-17 08:56:45
Usted podría hacer que los métodos privados o protegidos como públicos:
MyClass.send(:public, *MyClass.protected_instance_methods)
MyClass.send(:public, *MyClass.private_instance_methods)
Simplemente coloque este código en su clase de prueba sustituyendo su nombre de clase. Incluya el espacio de nombres si corresponde.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-28 22:41:00
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-04 14:35:18
Los métodos privados de pruebas unitarias parecen demasiado fuera de contexto con el comportamiento de la aplicación.
¿Estás escribiendo tu código de llamada primero? Este código no se llama en su ejemplo.
El comportamiento es: desea que se cargue un objeto desde otro objeto.
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
¿Por qué u quiere escribir la prueba fuera de contexto desde el comportamiento que debería estar tratando de describir?
¿Este código se usa en muchos lugares? Necesita un más genérico ¿acercarnos?
Https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/controller-specs/anonymous-controller
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-14 22:53:55
Use la gema rspec-context-private para hacer públicos temporalmente los métodos privados dentro de un contexto.
gem 'rspec-context-private'
Funciona añadiendo un contexto compartido a tu proyecto.
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
Entonces, si pasa :private
como metadatos a un bloque describe
, los métodos privados serán públicos dentro de ese contexto.
describe AccountController, :private do
it 'can test private methods' do
expect{subject.current_account}.not_to raise_error
end
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-24 17:24:30
Si necesita probar una función privada, cree un método público que invoque la función privada.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-18 23:42:41
Sé que esto es un poco hackeado, pero funciona si quieres los métodos comprobables por rspec pero no visibles en 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
Ahora cuando se puede ejecutar usted es spec así:
RAILS_ENV=test bundle exec rspec spec/foo_spec.rb
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-05 23:44:44