Revolution Rail Co. photo

Probando acciones de controladores sin ejecutar los filtros en Ruby on Rails

Muchas de las acciones de los controladores de una aplicacación Ruby on Rails tienen relacionado un método que se debe ejecutar antes que la propia acción, estós métodos están definidos por before_action.

Cuando probamos estas acciones en los controladores, lo que se quiere es probar la acción en si y no el método del before_action.

Como ejemplo de este artículo, la premisa es que la aplicación está construida en Ruby on Rails y se usa RSpec para las pruebas.

Uno de los métodos más usados en los filtros de controladores es el de verificar que el usuario esté autentificado, o en el caso de un API, que tenga el token de acceso.

module Api
module V1
class ApiController < ActionController::Base
respond_to :json
      before_action :restrict_access_by_token
      def ping
head :ok
end
      private
      def restrict_access_by_token
authenticate_or_request_with_http_token do |token|
@company = Company.find_by(api_token: token)
end
end
    end
end
end

Para la action ping se tiene lo siguiente en nuestro archivo de routes routes.rb

  namespace :api, defaults: {format: :json} do
scope module: :v1 do
match "ping", to: "api#ping", via: :get
end
end

Se quiere probar que la action ping tenga una respuesta favorable, para esto se ha escrito la siguiente prueba en el archivo spec/controllers/api_controller_spec.rb

require 'rails_helper'
RSpec.describe Api::V1::ApiController, type: :controller do
describe 'Api Controller Tests ' do
it ' success ping action ' do
get :ping
expect(response).to have_http_status(:success)
end
end
end

Al ejecutar las pruebas se tiene el siguiente resultado:

F
Failures:
1) Api::V1::ApiController Api Controller Tests   succes ping action 
Failure/Error: expect(response).to have_http_status(:success)
expected the response to have a success status code (2xx) but it was 401
# ./spec/controllers/api_controller_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 5.25 seconds (files took 3.69 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/api_controller_spec.rb:4 # Api::V1::ApiController Api Controller Tests   succes ping action

Esta falla se produce porque al ejecutar la acción restrict_access_by_token se produce un error que lanza una excepción.

Pero como, en este caso, no interesa probar el método restrict_access_by_token que debería ser probado individualmente, se plantean 2 trucos para que la prueba salte este filtro.

El primero es hacer una simulación de la respuesta del método restrict_access_by_token usando un RSpec Mock para simular la respuesta del método llamado por el filtro. Para este caso, se usó:

allow(controller).to receive(:restrict_access_by_token).and_return(true)

Entonces, el código de la prueba queda:

require 'rails_helper'
RSpec.describe Api::V1::ApiController, type: :controller do
describe 'Api Controller Tests ' do
it ' succes ping action ' do
allow(controller)
.to receive(:restrict_access_by_token)
.and_return(true)

get :ping
expect(response).to have_http_status(:success)
end
end
end

La otra opción propuesta es usar skip_before_action directamente en el código de la prueba. Así se tiene

require 'rails_helper'
RSpec.describe Api::V1::ApiController, type: :controller do
describe 'Api Controller Tests ' do
it ' succes ping action ' do
controller.class.skip_before_action :restrict_access_by_token
get :ping
expect(response).to have_http_status(:success)
end
end
end

También se tendría la opción de probar en conjunto todo. En este caso se deberá proveer en la prueba una cabecera de conexión que contenga un token válido.

Recomendación

Para el caso del ejemplo, es recomendable usar el método del skip_before_action ya que queda explícito en la prueba, que se está evitando realizar el filtro mencionado.

Para caso de validaciones, como permisos, verificaciones de banderas, etc, es preferible usar RSpec Mock para obtener el resultado deseado para cada caso.

Si te gustó este artículo, por favor aplaude las veces que quieras, y para ver historias similares acerca de tecnología, mira nuestras publicaciones y escribe en los comentarios cualquier duda que tengas o si quieres que escribamos de algo en particular.

Milber

Mail: milber@alturasoluciones.com
LinkedIn: https://www.linkedin.com/in/milberchamputiz/