ActionMailer: тест не пройден, но работает в среде разработки - PullRequest
3 голосов
/ 01 декабря 2011

ActionMailer в моем проекте на Rails 3.1 имеет странное поведение, ActionMailer :: Base.deliveries пуст в тесте, в то время как я могу получить письмо, запустив код в консоли rails. Кто-нибудь может указать, что это не так?

# spec/mailers/user_mailer_spec.rb
require "spec_helper"

describe UserMailer do
  describe ".reminding_email" do
    subject { UserMailer.reminding_email(user).deliver }
    let(:user) { create :confirmed_user_with_mass_tasks }
    it "should be delivered" do
      ActionMailer::Base.deliveries.should_not be_empty
    end
    its(:to) { should == [user.email] }
    its(:subject) { should == "Task Reminding" }
  end
end

# app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
  layout "email"
  default from: Rails.env.production? ? "<production>@gmail.com" : "<test>@gmail.com"
  def reminding_email(user)
    @tasks = user.tasks.reminding_required
    @current = Time.current
    mail(to: user.email, subject: "Task Reminding")
  end
end

Неудачи:

1) UserMailer.reminding_email должен быть доставлен Ошибка / Ошибка: ActionMailer :: Base.deliveries.should_not be_empty ожидается пустой? вернуть ложь, получил истину # ./spec/mailers/user_mailer_spec.rb:8:in `блок (3 уровня) в '

Завершено за 11,81 секунды. 42 примера, 1 сбой, 2 ожидающих

# config/environments/test.rb
RemindersForMe::Application.configure do
  # Settings specified here will take precedence over those in config/application.rb

  # The test environment is used exclusively to run your application's
  # test suite.  You never need to work with it otherwise.  Remember that
  # your test database is "scratch space" for the test suite and is wiped
  # and recreated between test runs.  Don't rely on the data there!
  config.cache_classes = true

  # Configure static asset server for tests with Cache-Control for performance
  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=3600"

  # Log error messages when you accidentally call methods on nil
  config.whiny_nils = true

  # Show full error reports and disable caching
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Raise exceptions instead of rendering exception templates
  config.action_dispatch.show_exceptions = false

  # Disable request forgery protection in test environment
  config.action_controller.allow_forgery_protection    = false

  # Tell Action Mailer not to deliver emails to the real world.
  # The :test delivery method accumulates sent emails in the
  # ActionMailer::Base.deliveries array.
  config.action_mailer.delivery_method = :test

  # Use SQL instead of Active Record's schema dumper when creating the test database.
  # This is necessary if your schema can't be completely dumped by the schema dumper,
  # like if you have constraints or database-specific column types
  # config.active_record.schema_format = :sql

  # Print deprecation notices to the stderr
  config.active_support.deprecation = :stderr

  # Setup default URL options as devise needed
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }
end

Применение:

# config/application.rb
require File.expand_path('../boot', __FILE__)

# Pick the frameworks you want:
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

if defined?(Bundler)
  # If you precompile assets before deploying to production, use this line
  # Bundler.require(*Rails.groups(:assets => %w(development test)))
  Bundler.require *Rails.groups(:assets) if defined?(Bundler)
  # If you want your assets lazily compiled in production, use this line
  # Bundler.require(:default, :assets, Rails.env)
end

module RemindersForMe
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Custom directories with classes and modules you want to be autoloadable.
    # config.autoload_paths += %W(#{config.root}/extras)

    # Only load the plugins named here, in the order given (default is alphabetical).
    # :all can be used as a placeholder for all plugins not explicitly named.
    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]

    # Activate observers that should always be running.
    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # Configure the default encoding used in templates for Ruby 1.9.
    config.encoding = "utf-8"

    # Configure sensitive parameters which will be filtered from the log file.
    config.filter_parameters += [:password]

    # Enable the asset pipeline
    config.assets.enabled = true

    # Version of your assets, change this if you want to expire all your assets
    config.assets.version = '1.0'

    # Set Rspec generator as default
    config.generators do |g|
      g.test_framework :rspec
    end

    # Set Mailer of Devise
    config.to_prepare do
      Devise::Mailer.layout "email"
    end
  end
end

Теперь измените спецификацию следующим образом:

require "spec_helper"

describe UserMailer do
  describe ".reminding_email" do
    subject { UserMailer.reminding_email(user) }
    let(:user) { create :confirmed_user_with_undue_tasks }
    it { expect { subject.deliver }.to change { ActionMailer::Base.deliveries.length }.by(1) }
    its(:to) { should == [user.email] }
    its(:subject) { should == "Task Reminding" }
  end
end

1) UserMailer.reminding_email Сбой / Ошибка: он {ожидает {subject.deliver}. Чтобы изменить {ActionMailer :: Base.deliveries.length} .by (1)} результат должен был быть изменен на 1, но был изменен на 2 # ./spec/mailers/user_mailer_spec.rb:7:in `блок (3 уровня) в '

Ответы [ 4 ]

8 голосов
/ 06 января 2012

У меня была похожая проблема, и это произошло потому, что я тестировал электронную почту Devise: Devise использует отдельный почтовик, поэтому вам нужно получить доступ к Devise.mailer.deliveries вместо ActionMailer::Base.deliveries.

1 голос
/ 22 марта 2013

По умолчанию Action Mailer не отправляет электронные письма в тестовой среде. Они просто добавляются в массив ActionMailer :: Base.deliveries. (См. Раздел 6 в http://guides.rubyonrails.org/action_mailer_basics.html)

Что означает «по умолчанию», так это то, что вы не должны предоставлять эффективные настройки email_delivery для тестовой среды. Если в config / configuration.yml есть действующие настройки по умолчанию для email_delivery, вы можете переопределить их с помощью:

test:
  email_delivery:
    delivery_method: :test
1 голос
/ 01 декабря 2011

Вы должны проверить разделенные свойства почты:

describe UserMailer do
  describe ".reminding_email" do
    subject { UserMailer.reminding_email(user)}
    let(:user) { create :confirmed_user_with_mass_tasks }
    it{ expect{subject.deliver}.to change{ActionMailer::Base.deliveries.length}.by(1)}
    its(:to) { should == [user.email] }
    its(:subject) { should == "Task Reminding" }
  end
end

Обратите внимание на изменение темы, потому что ваш почтовик, как и должно, возвращает результат метода mail, который уже инициализирован с toи subject.

0 голосов
/ 01 декабря 2011

Как вы настраиваете ActionMailer?Это в вашем файле config / application.rb или в определенных файлах environment / *. Rb?

Помните, что все, что вы указываете в файлах environment / *. Rb, имеет приоритет над файлом config / application.rb.

Так что, возможно, ваша проблема в том, что при работе в тестовом режиме ActionMailer использует: smtp, а не: test?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...