Подтвердить что ты не робот

Как проверить, что переменная экземпляра установлена ​​в моей моей почтовой программе с помощью rspec?

Как проверить, что определенная переменная экземпляра установлена ​​в моей моей почтовой программе с помощью rspec? присваивает возвращается 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

Возвращенная ошибка:

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

Ответ 1

assigns определяется только для спецификаций контроллера и выполняется с помощью rspec-rails gem. В RSpec нет общего механизма проверки переменных экземпляра, но вы можете использовать Kernel instance_variable_get для доступа к любой переменной экземпляра, которую вы хотите.

Итак, в вашем случае, если object был объектом, переменная экземпляра которого вы интересовали, вы можете написать:

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

Что касается получения экземпляра UserMailer, я не вижу никакого способа сделать это. Глядя на определение method_missing внутри https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb, новый экземпляр почтовой программы будет создан всякий раз, когда вызывается метод класса undefined с тем же именем, что и метод экземпляра, Но этот экземпляр не сохраняется нигде, что я вижу, и возвращается только значение .message. Вот соответствующий код, определенный в настоящее время в github:

Методы класса:

  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

Методы экземпляра:

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

Ответ 2

Я не думаю, что это возможно проверить, если Rails не изменит свою реализацию, так что он фактически обеспечивает доступ к объекту ActionMailer (controller), а не только к создаваемому объекту Mail.

Как отметил Питер Альфвин, проблема в том, что он возвращает "сообщение" здесь:

new(method_name, *args).message

вместо того, чтобы просто возвращать почтовую программу (контроллер) следующим образом:

new(method_name, *args)

Этот post в списке rspec-rails также может быть полезен:

Кажется разумным, но вряд ли изменится. Вот почему. RSpec рельсы обеспечивает обертки вокруг тестовых классов, предоставляемых рельсами. Рельсы функциональные тесты поддерживают три вопроса, которые вы ставите выше, но рельсы тесты почтовой программы отличаются. Из http://guides.rubyonrails.org/action_mailer_basics.html: "Тестирование почтовые программы обычно связаны с двумя вещами: во-первых, почта была поставлена ​​в очередь, а другой - правильно."

Чтобы поддерживать то, что вы хотели бы видеть в спецификациях почтовой программы, rspec-rails должны предоставить ему собственную ExampleGroup (а не обернуть рельсы класс), который должен быть тесно связан с внутренними элементами рельсов. я приложили большие усилия в rspec-rails-2, чтобы ограничить связь с общественностью API, и у этого был большой выигрыш: у нас был только один случай, когда rails 3.x требуется выпуск rspec-рельсов (т.е. был нарушение изменение). С рельсами-2 почти в каждом выпуске rspec-rails, потому что rspec-рельсы были привязаны к внутренним (rspec-rails ' неисправность, а не рельсы).

Если вы действительно хотите увидеть это изменение, вам нужно его изменить в рельсах, и в этот момент rspec-rails с радостью и улучшенный MailerTestCase.