使用RSpec测试ActionMailer多部分电子邮件

时间:2011-06-27 00:13:05

标签: ruby ruby-on-rails-3 testing rspec actionmailer

我目前正在使用RSpec测试我的邮件程序,但我已经开始按照Rails指南中的说明设置多部分电子邮件:http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

我有文本和html格式的邮件模板,但看起来我的测试只检查HTML部分。有没有办法单独检查文本模板?

是否仅检查HTML视图,因为它是默认顺序中的第一个?

5 个答案:

答案 0 :(得分:32)

为了补充,nilmethod的优秀答案,您可以通过使用共享示例组测试text和html版本来清理您的规范:

spec_helper.rb

def get_message_part (mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }.body.raw_source
end

shared_examples_for "multipart email" do
  it "generates a multipart message (plain text and html)" do
    mail.body.parts.length.should eq(2)
    mail.body.parts.collect(&:content_type).should == ["text/plain; charset=UTF-8", "text/html; charset=UTF-8"]
  end
end

your_email_spec.rb

let(:mail) { YourMailer.action }

shared_examples_for "your email content" do
  it "has some content" do
    part.should include("the content")
  end
end

it_behaves_like "multipart email"

describe "text version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /plain/) }
  end
end

describe "html version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /html/) }
  end
end

答案 1 :(得分:27)

这可以使用正则表达式进行测试。

在HTML部分中查找内容(在此之后使用#should匹配):

mail.body.parts.find {|p| p.content_type.match /html/}.body.raw_source

在纯文本部分中查找内容(在此之后使用#should匹配):

mail.body.parts.find {|p| p.content_type.match /plain/}.body.raw_source

检查确实是否正在生成多部分消息:

it "generates a multipart message (plain text and html)" do
  mail.body.parts.length.should == 2
  mail.body.parts.collect(&:content_type).should == ["text/html; charset=UTF-8", "text/plain; charset=UTF-8"]
end 

答案 2 :(得分:23)

为了使事情变得更简单,您可以使用

message.text_part    and
message.html_part

找到各自的部分。这适用于带附件的结构化多部分/备用消息。 (使用Rails 3.0.14在Ruby 1.9.3上测试过。)

这些方法使用某种启发式方法来查找相应的消息部分,因此如果您的消息包含多个文本部分(例如Apple Mail创建它们),则可能无法执行“正确的操作”。

这会将上述方法改为

def body_should_match_regex(mail, regex)
 if mail.multipart?
  ["text", "html"].each do |part|
   mail.send("#{part}_part").body.raw_source.should match(regex)
  end
 else
  mail.body.raw_source.should match(regex)
 end
end

适用于纯文本(非多部分)消息和多部分消息,并针对特定正则表达式测试所有消息体。

现在,有没有志愿者为此制作一个“真正的”RSpec匹配器? :)像

这样的东西
@mail.bodies_should_match /foobar/

会更好......

答案 3 :(得分:1)

如果您的电子邮件包含附件,则文本和html部分将放在multipart/alternative部分中。这在Sending Emails with Attachments in the Rails 3 Guide下注明。

为了解决这个问题,我首先将上面的get_message_part方法简化为:

def get_message_part(mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }
end

然后在我的测试中:

multipart = get_message_part(email, /multipart/)

html = get_message_part(multipart, /html/)
html_body = html.body.raw_source

assert_match 'some string', html_body

答案 4 :(得分:0)

我已经这样做了,我发现它更简单,因为除了样式和标记外,两封电子邮件的内容都将相似。

context 'When there are no devices' do
  it 'makes sure both HTML and text version emails are sent' do
    expect(mail.body.parts.count).to eq(2)
    # You can even make sure the types of the part are `html` and `text`
  end

  it 'does not list any lockboxes to be removed in both types emails' do
    mail.body.parts.each do |part|
      expect(part.body).to include('No devices to remove')
    end
  end
end