tutorial rails matchers generate factory_girl_rails bot ruby-on-rails-3 rspec ruby-on-rails-3.1 routes

ruby-on-rails-3 - matchers - rspec rails tutorial



¿Cómo escribo una prueba de controlador de motor Rails 3.1 en rspec? (6)

En base a this respuesta elegí la siguiente solución:

#spec/spec_helper.rb RSpec.configure do |config| # other code config.before(:each) { @routes = UserManager::Engine.routes } end

El beneficio adicional es que no necesita tener el bloque before(:each) en cada controlador-especificación.

Escribí un motor Rails 3.1 con las publicaciones del espacio de nombres. Por lo tanto, mis controladores se encuentran en la aplicación / controladores / publicaciones /, mis modelos en la aplicación / modelos / publicaciones, etc. Puedo probar los modelos muy bien. La especificación para un modelo parece ...

module Posts describe Post do describe ''Associations'' do it ... end

... y todo funciona bien

Sin embargo, las especificaciones para los controladores no funcionan. El motor Rails está montado en / posts, pero el controlador es Posts :: PostController. Por lo tanto, las pruebas buscan que la ruta del controlador sea publicaciones / publicaciones.

describe "GET index" do it "assigns all posts as @posts" do Posts::Post.stub(:all) { [mock_post] } get :index assigns(:posts).should eq([mock_post]) end end

cuyos rendimientos...

1) Posts::PostsController GET index assigns all posts as @posts Failure/Error: get :index ActionController::RoutingError: No route matches {:controller=>"posts/posts"} # ./spec/controllers/posts/posts_controller_spec.rb:16

He intentado todo tipo de trucos en el archivo de rutas de la aplicación de prueba ...: espacio de nombres, etc., en vano.

¿Cómo hago que esto funcione? Parece que no lo hará, ya que el motor pone el controlador en / posts, pero el espacio de nombres pone al controlador en / posts / posts con el propósito de probar.


Estoy desarrollando una joya para mi empresa que proporciona una API para las aplicaciones que estamos ejecutando. Estamos usando Rails 3.0.9 todavía, con los últimos Rspec-Rails (2.10.1). Estaba teniendo un problema similar donde había definido rutas como esa en mi gema del motor Rails.

match ''/companyname/api_name'' => ''CompanyName/ApiName/ControllerName#apimethod''

Me estaba dando un error como

ActionController::RoutingError: No route matches {:controller=>"company_name/api_name/controller_name", :action=>"apimethod"}

Resultó que solo necesitaba redefinir mi ruta en guiones bajos para que RSpec pudiera hacerla coincidir.

match ''/companyname/api_name'' => ''company_name/api_name/controller_name#apimethod''

Supongo que las pruebas del controlador Rspec usan una búsqueda inversa basada en el caso de subrayado, mientras que Rails configurará e interpretará la ruta si la defines en camelcase o guión bajo.


He solucionado este problema anulando los métodos get , post , put y delete que se proporcionan, por lo que siempre pasan use_route como parámetro.

Utilicé la respuesta de Benoit como base para esto. ¡Gracias amigo!

module ControllerHacks def get(action, parameters = nil, session = nil, flash = nil) process_action(action, parameters, session, flash, "GET") end # Executes a request simulating POST HTTP method and set/volley the response def post(action, parameters = nil, session = nil, flash = nil) process_action(action, parameters, session, flash, "POST") end # Executes a request simulating PUT HTTP method and set/volley the response def put(action, parameters = nil, session = nil, flash = nil) process_action(action, parameters, session, flash, "PUT") end # Executes a request simulating DELETE HTTP method and set/volley the response def delete(action, parameters = nil, session = nil, flash = nil) process_action(action, parameters, session, flash, "DELETE") end private def process_action(action, parameters = nil, session = nil, flash = nil, method = "GET") parameters ||= {} process(action, parameters.merge!(:use_route => :my_engine), session, flash, method) end end RSpec.configure do |c| c.include ControllerHacks, :type => :controller end


Solución para un problema cuando no tiene o no puede usar isolate_namespace :

module Posts class Engine < Rails::Engine end end

En las especificaciones del controlador, para arreglar las rutas:

get :show, {:id => 1, :use_route => :posts_engine}

Rails agrega _engine a las rutas de tu aplicación si no usas isolate_namespace .


Supongo que estás probando tu motor con una aplicación de rieles ficticios, como la que generaría enginex .

Su motor debe estar montado en la aplicación ficticia:

En spec/dummy/config/routes.rb :

Dummy::Application.routes.draw do mount Posts::Engine => ''/posts-prefix'' end

Mi segunda suposición es que su motor está aislado:

En lib/posts.rb :

module Posts class Engine < Rails::Engine isolate_namespace Posts end end

No sé si estas dos suposiciones son realmente necesarias, pero así es como mi propio motor está estructurado.

La solución es bastante simple, en lugar de esto

get :show, :id => 1

utilizar esta

get :show, {:id => 1, :use_route => :posts}

El símbolo :posts debe ser el nombre de su motor y NO la ruta donde está montado.

Esto funciona porque los parámetros del método get se pasan directamente a ActionDispatch::Routing::RouteSet::Generator#initialize (definido here ), que a su vez usa @named_route para obtener la ruta correcta de Rack::Mount::RouteSet#generate ( mira here y here ).

Sumergirse en los componentes internos de los rieles es divertido, pero lleva mucho tiempo, no haría esto todos los días ;-).

HTH


Use la directiva de routes rspec-rails:

describe MyEngine::WidgetsController do routes { MyEngine::Engine.routes } # Specs can use the engine''s routes & named URL helpers # without any other special code. end

- RSpec Rails 2.14 documentos oficiales .