讲到测试邮件发送程序,我们首先要让系统可以发送邮件。我们先来给系统添加发送邮件的功能。
Action Mailer in Rails 3是一个不错的视频教程,大家可以参考。
还有就是http://guides.rubyonrails.org/action_mailer_basics.html中更加详细的介绍。
添加邮件发送程序
发送邮件要保证我们有目标邮箱,所以呢,我们的用户要有一个属性:email。
还是拿我的blog项目作为练习项目。
我们在用户注册的时候给他发一封邮件。
首先我们创建一个初始化文件
config/initializers/setup_mail.rb,初始化邮箱相关的信息。
- ActionMailer::Base.smtp_settings = {
- :address => "smtp.163.com",
- :port => 25,
- :domain => "163.com",
- :user_name => "woaiguanshui2012",
- :password => "123456asdf",
- :authentication => "plain",
- :enable_starttls_auto => true
- }
我们使用163的邮箱作为邮件发送服务器,需要我们在上面有一个注册用户,这里我注册一个woaiguanshui201,密码是123456asdf。
创建邮件发送程序
然后用rails g mailer命令创建一个mailer程序。
- rails g mailer user_mailer
命令会创建app/mailers/user_mailer.rb文件。
- class UserMailer < ActionMailer::Base
- default :from => "woaiguanshui2012@163.com"
- end
在里面添加一个方法,用来在用户注册的时候给用户发邮件。
- class UserMailer < ActionMailer::Base
- default :from => "woaiguanshui2012@163.com"
- def registration_confirmation(user)
- mail(:to => user.email, :subject => "Registered")
- end
- end
创建邮件内容模板
邮件的内容也可以通过模板来实现,和controller的action对应有一个view一样。我们的mailer的方法也需要一个view来做模板。
创建app/views/user_mailer/registration_confirmation.text.erb文件,在文件中写入下面的内容。
- Thank you for registering!
调用邮件发送程序
上下最后一步了,就是在用户注册成功之后,调用这个mailer程序的registration_confirmation方法,就可以发送我们预定义的模板文件中的内容了。
我们把用户注册的方法修改一下,userscontroller的create方法。
- def create
- @user = User.new(params[:user])
- if @user.save
- UserMailer.registration_confirmation(@user).deliver
- flash[:notice] = "sign up successfully!"
- signin(@user)
- redirect_to root_path
- else
- flash.now[:notice] = "sign up failed!"
- render :new
- end
- end
UserMailer.registration_confirmation(@user).deliver
上面这一行是我们新加入的,就是发邮件用的。
这时候启动我们的服务rails s,然后注册一个用户,然后看看用户的邮箱,就应该有了一封从woaiguanshui2012@163发来的邮件,标题是Registered,内容是thank you for registering!。
这就说明我们的邮件发送程序正常工作了。
丰富邮件内容模板
我们还可以丰富一下邮件的内容,比如添加用户的信息。修改registration_confirmation.text.erb文件。
- Hi, <%= @user.nickname %>
- Thank you for registering!
- Welcome to come back!
这就需要我们在registration_comfirmation方法中添加一个返回的变量@user。
- def registration_confirmation(user)
- @user = user
- mail(:to => user.email, :subject => "Registered")
- end
在模板中使用url的话,比如说edit_user_url(@user.id, :host => "localhost:3000"),这时候就只能使用_url方法,不能使用_path方法,同时还需要指定host。这是因为邮件客户端没有web的上下文环境,不像controller中是有web的上下文环境的,所以不需要指定host。当然,每次指定还是比较麻烦的,你也可以在前面创建的配置文件config/initializers/setup_mail.rb中添加下面的一样。
- ActionMailer::Base.default_url_options[:host] = "localhost:3000"
这样就可以省略url中的host参数了。
在邮件中添加附件
- def registration_confirmation(user)
- @user = user
- p_w_uploads["rails.png"] = File.read("#{Rails.root}/public/p_w_picpaths/rails.png")
- mail(:to => "#{user.name} <#{user.email}>", :subject => "Registered")
- 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
上面的测试中,首先测试邮件队列是否不为空,然后测试邮件的目标地址是否正确。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/tech/opensource/192037.html