使用RSpec测试ActionMailer多部分邮件(文本和HTML版本)。

问题描述 投票:31回答:4

我目前正在用RSpec测试我的邮件,但我已经开始按照这里的Rails指南中的描述设置多部分邮件。 http:/guides.rubyonrails.orgaction_mailer_basics.html#sending-multipart-emails。

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

是不是因为HTML视图是默认顺序中的第一个,所以只检查HTML视图?

ruby ruby-on-rails-3 rspec actionmailer multipart
4个回答
33
投票

为了补充nilmethod的出色回答,您可以通过使用共享示例组测试文本和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

你的电子邮件_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

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 

23
投票

为了让事情更简单,你可以使用

message.text_part    and
message.html_part

以找到相应的部分。这甚至适用于带附件的结构化多部分替代消息。(在Ruby 1.9.3和Rails 3.0.14上测试。)

这些方法采用了某种启发式的方法来查找各自的消息部分,所以如果你的消息有多个文本部分(例如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/

会好很多...


1
投票

如果您的电子邮件有附件,文本和HTML部分将被放置在一个新的附件中。multipart/alternative 部分。这一点在下文中已经指出。在Rails 3指南中使用附件发送电子邮件.

为了处理这个问题,我首先简化了 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

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
© www.soinside.com 2019 - 2024. All rights reserved.