unitarias test rails pruebas ruby-on-rails rspec instance-variables

ruby on rails - test - ¿Cómo puedo probar que una variable de instancia está configurada en mi correo con rspec?



tdd ruby on rails (2)

¿Cómo compruebo que una determinada variable de instancia está configurada en mi correo con rspec? asigna está volviendo indefinido ..

require File.dirname(__FILE__) + ''/../../spec_helper'' describe UserMailer do it "should send the member user password to a User" do user = FG.create :user user.create_reset_code mail = UserMailer.reset_notification(user).deliver ActionMailer::Base.deliveries.size.should == 1 user.login.should be_present assigns[:person].should == user assigns(:person).should == user #both assigns types fail end end

El error devuelto es:

undefined local variable or method `assigns'' for #<RSpec::Core::ExampleGroup::Nested_1:0x007fe2b88e2928>


No creo que esto sea posible probar a menos que Rails cambie su implementación para que realmente brinde acceso al objeto ActionMailer (controlador) y no solo al objeto Mail que se genera.

Como señaló Peter Alfvin, el problema es que devuelve el ''mensaje'' aquí:

new(method_name, *args).message

En lugar de simplemente devolver el correo (controlador) de esta manera:

new(method_name, *args)

Esta post en la lista de rspec-rails también podría ser útil:

Parece razonable, pero es poco probable que cambie. Este es el por qué. rspec-rails proporciona envolturas alrededor de las clases de prueba proporcionadas por los rieles. Las pruebas funcionales de Rails son compatibles con las tres preguntas que plantea arriba, pero las pruebas de envío de Rails son diferentes. De http://guides.rubyonrails.org/action_mailer_basics.html : "Probar los correos electrónicos normalmente involucra dos cosas: una es que el correo se puso en cola y la otra es que el correo electrónico es correcto".

Para admitir lo que le gustaría ver en las especificaciones de la aplicación de correo, rspec-rails tendría que proporcionar su propio ExampleGroup (en lugar de envolver la clase de rails), que tendría que estar estrechamente ligados a las partes internas de rails. Me esforcé mucho en rspec-rails-2 para restringir el acoplamiento a las API públicas, y esto ha tenido una gran recompensa: solo hemos tenido un caso en el que una versión 3.x de rails requería una versión de rspec-rails (es decir, hubo un cambio de ruptura). Con los rieles-2, casi todos los lanzamientos rompieron rspec-rails porque rspec-rails estaba atado a los internos (falla de rspec-rails, no rails).

Si realmente desea ver este cambio, deberá cambiarlo en los rieles, momento en el que rspec-rails envolverá el nuevo y mejorado MailerTestCase.


assigns solo se definen para las especificaciones del controlador y se realizan a través de la gema rspec-rails. No hay un mecanismo general para probar las variables de instancia en RSpec, pero puede usar el instance_variable_get de Kernel para acceder a cualquier variable de instancia que desee.

Entonces, en su caso, si el object fuera la variable de instancia que estaba interesado en verificar, podría escribir:

expect(object.instance_variable_get(:@person)).to eql(user)

En cuanto a obtener UserMailer instancia de UserMailer , no puedo ver ninguna forma de hacerlo. Mirando la definición de method_missing dentro de https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb , se creará una nueva instancia de correo cada vez que se llame a un método de clase no definido con el mismo nombre como método de instancia. Pero esa instancia no se guarda en ningún lugar que pueda ver y solo se devuelve el valor de .message . Aquí está el código relevante como se define actualmente en github:

Métodos de clase:

def respond_to?(method, include_private = false) #:nodoc: super || action_methods.include?(method.to_s) end def method_missing(method_name, *args) # :nodoc: if respond_to?(method_name) new(method_name, *args).message else super end end

Métodos de instancia:

attr_internal :message # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer # will be initialized according to the named method. If not, the mailer will # remain uninitialized (useful when you only need to invoke the "receive" # method, for instance). def initialize(method_name=nil, *args) super() @_mail_was_called = false @_message = Mail.new process(method_name, *args) if method_name end def process(method_name, *args) #:nodoc: payload = { mailer: self.class.name, action: method_name } ActiveSupport::Notifications.instrument("process.action_mailer", payload) do lookup_context.skip_default_locale! super @_message = NullMail.new unless @_mail_was_called end end