unitarias test rails pruebas hacer español como ruby-on-rails rspec

ruby-on-rails - pruebas - ruby on rails test



Rspec, Rails: ¿cómo probar métodos privados de controladores? (10)

Tengo el 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?

PD: uso Rspec2 y Ruby on Rails 3


¿Dónde se usa el método current_account? ¿Para qué sirve?

En general, no prueba métodos privados sino que prueba los métodos que llaman el privado.


Las pruebas unitarias de métodos privados 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 tu ejemplo.

El comportamiento es: quieres un objeto cargado 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é quieres escribir la prueba fuera de contexto del comportamiento que deberías tratar de describir?

¿Este código se usa en muchos lugares? ¿Necesita un enfoque más genérico?

https://www.relishapp.com/rspec/rspec-rails/v/2-8/docs/controller-specs/anonymous-controller


No debe probar sus métodos privados directamente, pueden y deben probarse indirectamente mediante el uso del código de métodos públicos.

Esto le permite cambiar las partes internas de su código más adelante sin tener que cambiar sus pruebas.


Puede hacer que sus métodos privados o protegidos sean 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.


Sé que esto es un poco hacky, pero funciona si quieres que los métodos sean 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 puedes ejecutar, tienes las siguientes especificaciones:

RAILS_ENV=test bundle exec rspec spec/foo_spec.rb


Si necesita probar una función privada, cree un método público que invoca el privado.


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


Use la gema rspec-context-private para hacer públicos temporalmente los métodos privados dentro de un contexto.

gem ''rspec-context-private''

Funciona al agregar un contexto compartido a su 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

Luego, si pasa :private como metadato a un bloque de 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


Yo uso el método de envío. P.ej:

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

Porque "enviar" puede llamar a métodos privados


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