Pytanie jak mogę przetestować, czy zmienna instancji jest ustawiona w moim mailerze za pomocą rspec?


Jak mogę przetestować, że pewna zmienna instancji jest ustawiona w moim mailerze za pomocą rspec? assigns wraca undefined ..

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

Zwrócony błąd to:

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

18
2018-01-12 21:18


pochodzenie




Odpowiedzi:


assigns jest zdefiniowany tylko dla kontroler specs i odbywa się za pośrednictwem klejnotów rspec-rails. Nie ma żadnego ogólnego mechanizmu do testowania zmiennych instancji w RSpec, ale możesz użyć Kernela instance_variable_get aby uzyskać dostęp do dowolnej zmiennej instancji, którą chcesz.

A więc w twoim przypadku, jeśli object był obiekt, którego zmienną instancji interesowałeś, możesz napisać:

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

Jeśli chodzi o uzyskanie dostępu do UserMailer na przykład, nie widzę żadnego sposobu, aby to zrobić. Patrząc na method_missing definicja wewnątrz https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb, nowa instancja programu pocztowego zostanie utworzona za każdym razem, gdy zostanie wywołana niezdefiniowana metoda klasy o tej samej nazwie co metoda instancji. Ale ta instancja nie jest zapisana nigdzie, co widzę i tylko wartość .message jest zwracany. Oto odpowiedni kod, jak obecnie zdefiniowany na github:

Metody klasowe:

  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

Metody instancji:

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

22
2018-01-12 21:27



więc szyny rspec nie pozwalają na testowanie instancji vars w programach pocztowych? Minitest ma ... - pixelearth
Zobacz zaktualizowaną odpowiedź. - Peter Alfvin
Jest to użyteczne, z wyjątkiem tego przypadku, nie jestem pewien, który obiekt miałby ustawione te vars instancji. Jakieś pomysły? - pixelearth
Nie jestem pewny. Zwykle podczas sprawdzania wartości zmiennej instancji, w szczególności patrzysz na jakiś kod. Jaki kod próbujemy przetestować wartość @person dla? - Peter Alfvin
Zobacz zaktualizowany komunikat o tym, jak trafiłem na koniec mojej liny. ;-) - Peter Alfvin


Nie sądzę, że jest to możliwe do sprawdzenia, chyba że Railsy zmieniają jego implementację, tak aby faktycznie zapewniał dostęp do obiektu ActionMailer (kontroler), a nie tylko do generowanego obiektu Mail.

Jak zauważył Peter Alfvin, problem polega na tym, że zwraca "wiadomość" tutaj:

new(method_name, *args).message

zamiast po prostu zwrócić program pocztowy (kontroler) w ten sposób:

new(method_name, *args)

To stanowisko na liście rspec-rails mogą być pomocne:

Wydaje się rozsądne, ale mało prawdopodobne, aby się zmienić. Dlatego. rspec-rails   zapewnia owijki wokół klas testowych dostarczanych przez szyny. Szyny   testy funkcjonalne wspierają trzy pytania, które poznasz powyżej, ale szyny   Testy mailera są różne. Od    http://guides.rubyonrails.org/action_mailer_basics.html: "Testowanie   mailers zwykle obejmuje dwie rzeczy: Po pierwsze, poczta była w kolejce,   a drugi e-mail jest poprawny. "

Aby wspierać to, co chcesz zobaczyć w specyfikacjach mailer, zrobilibyśmy rspec-rails   musisz podać swoją własną grupę przykładową (zamiast owijać szyny)   klasa), które musiałyby być ściśle związane z wewnętrznymi szynami. ja   zadał sobie trud w rspec-rails-2, aby ograniczyć sprzężenie z publicznością   API, i to miało dużą korzyść: mieliśmy tylko jeden przypadek, w którym a   wydanie 3.x rails wymagało wydania rspec-rails (tj   zerwanie zmiany). Z szynami-2 prawie wszystkie wersje się zepsuły   rspec-rails, ponieważ rspec-rails był powiązany z internals (rspec-rails '   wina, nie szyny).

Jeśli naprawdę chcesz zobaczyć tę zmianę, musisz ją zmienić   w samych szynach, w którym punkt rspec-rails z przyjemnością otoczy nowy   i ulepszona MailerTestCase.


2
2018-03-10 17:42