千家信息网

Rails测试《十一》添加邮件发送程序及测试邮件发送程序

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,讲到测试邮件发送程序,我们首先要让系统可以发送邮件。我们先来给系统添加发送邮件的功能。Action Mailer in Rails 3是一个不错的视频教程,大家可以参考。还有就是http://guid
千家信息网最后更新 2025年02月01日Rails测试《十一》添加邮件发送程序及测试邮件发送程序

讲到测试邮件发送程序,我们首先要让系统可以发送邮件。我们先来给系统添加发送邮件的功能。

Action Mailer in Rails 3是一个不错的视频教程,大家可以参考。

还有就是http://guides.rubyonrails.org/action_mailer_basics.html中更加详细的介绍。

添加邮件发送程序

发送邮件要保证我们有目标邮箱,所以呢,我们的用户要有一个属性:email。

还是拿我的blog项目作为练习项目。

我们在用户注册的时候给他发一封邮件。

首先我们创建一个初始化文件

config/initializers/setup_mail.rb,初始化邮箱相关的信息。

  1. ActionMailer::Base.smtp_settings = {
  2. :address => "smtp.163.com",
  3. :port => 25,
  4. :domain => "163.com",
  5. :user_name => "woaiguanshui2012",
  6. :password => "123456asdf",
  7. :authentication => "plain",
  8. :enable_starttls_auto => true
  9. }

我们使用163的邮箱作为邮件发送服务器,需要我们在上面有一个注册用户,这里我注册一个woaiguanshui201,密码是123456asdf。

创建邮件发送程序

然后用rails g mailer命令创建一个mailer程序。

  1. rails g mailer user_mailer

命令会创建app/mailers/user_mailer.rb文件。

  1. class UserMailer < ActionMailer::Base
  2. default :from => "woaiguanshui2012@163.com"
  3. end

在里面添加一个方法,用来在用户注册的时候给用户发邮件。

  1. class UserMailer < ActionMailer::Base
  2. default :from => "woaiguanshui2012@163.com"
  3. def registration_confirmation(user)
  4. mail(:to => user.email, :subject => "Registered")
  5. end
  6. end

创建邮件内容模板

邮件的内容也可以通过模板来实现,和controller的action对应有一个view一样。我们的mailer的方法也需要一个view来做模板。

创建app/views/user_mailer/registration_confirmation.text.erb文件,在文件中写入下面的内容。

  1. Thank you for registering!

调用邮件发送程序

上下最后一步了,就是在用户注册成功之后,调用这个mailer程序的registration_confirmation方法,就可以发送我们预定义的模板文件中的内容了。

我们把用户注册的方法修改一下,userscontroller的create方法。

  1. def create
  2. @user = User.new(params[:user])
  3. if @user.save
  4. UserMailer.registration_confirmation(@user).deliver
  5. flash[:notice] = "sign up successfully!"
  6. signin(@user)
  7. redirect_to root_path
  8. else
  9. flash.now[:notice] = "sign up failed!"
  10. render :new
  11. end
  12. end

UserMailer.registration_confirmation(@user).deliver

上面这一行是我们新加入的,就是发邮件用的。

这时候启动我们的服务rails s,然后注册一个用户,然后看看用户的邮箱,就应该有了一封从woaiguanshui2012@163发来的邮件,标题是Registered,内容是thank you for registering!。

这就说明我们的邮件发送程序正常工作了。

丰富邮件内容模板

我们还可以丰富一下邮件的内容,比如添加用户的信息。修改registration_confirmation.text.erb文件。

  1. Hi, <%= @user.nickname %>
  2. Thank you for registering!
  3. Welcome to come back!

这就需要我们在registration_comfirmation方法中添加一个返回的变量@user。

  1. def registration_confirmation(user)
  2. @user = user
  3. mail(:to => user.email, :subject => "Registered")
  4. end

在模板中使用url的话,比如说edit_user_url(@user.id, :host => "localhost:3000"),这时候就只能使用_url方法,不能使用_path方法,同时还需要指定host。这是因为邮件客户端没有web的上下文环境,不像controller中是有web的上下文环境的,所以不需要指定host。当然,每次指定还是比较麻烦的,你也可以在前面创建的配置文件config/initializers/setup_mail.rb中添加下面的一样。

  1. ActionMailer::Base.default_url_options[:host] = "localhost:3000"

这样就可以省略url中的host参数了。

在邮件中添加附件

  1. def registration_confirmation(user)
  2. @user = user
  3. p_w_uploads["rails.png"] = File.read("#{Rails.root}/public/p_w_picpaths/rails.png")
  4. mail(:to => "#{user.name} <#{user.email}>", :subject => "Registered")
  5. end

再次注册用户,然后登录用户的邮箱,就会发现收到了一封带有附件的邮件。

关于邮件发送还有很多,大家在使用和设计的过程中会有更多的体会。比如说我们现在的发送邮件和用户注册是同步处理的,这样的话,大量用户注册,就会严重拖慢系统,甚至拖垮系统。邮件没有必要和用户注册同步处理,可以做成异步的,可以做成独立的job。这时候邮件发送就需要独立出来,可以搞成一个邮件队列,只要在用户注册的时候发送一个邮件消息给邮件队列,由队列负责具体的发送工作就可以了。

测试邮件发送程序

关于邮件测试有下面几个目的

  • 邮件正在被处理,创建或者发送。
  • 邮件的内容是正确的,包括标题,发送人,body等。
  • 在正确的时间发送了正确的邮件。

可以从两个方向来测试邮件,一个是单元测试,一个是功能测试。在单元测试中,我们在一个隔离的环境中运行邮件程序,内容是受控的,然后和模拟数据比较输出的内容。在功能测试中,我们在controller和model中正确的使用邮件发送程序,测试在正确的时间发送了正确的邮件。


默认情况下,测试环境是不能发邮件的。他们只会把邮件加入ActionMailer::Base.deliveries数组,通过判断数组不为空,就可以知道邮件是否发送成功。

测试邮件就是两件事:

  • 测试邮件是否加入队列。
  • 测试邮件内容是否正确。

test/unit/user_mailer_test.rb

  • require 'test_helper'
  • class UserMailerTest < ActionMailer::TestCase
  • include FactoryGirl::Syntax::Methods
  • def test_registration_confirmation
  • user = FactoryGirl.create(:user_valid)
  • mail = UserMailer.registration_confirmation(user).deliver
  • assert !ActionMailer::Base.deliveries.empty?
  • assert_equal [user.email], mail.to
  • end
  • end

上面的测试中,首先测试邮件队列是否不为空,然后测试邮件的目标地址是否正确。

0