К сожалению, RSpec не предоставляет хелперы для тестирование мейлеров, вроде тех, что есть в TestUnit. Но добавить их в приложение совсем несложно, и в данной заметке я покажу, как это сделать.
Для начала, нам нужно определить хелпер для чтения фикстур и положить их в файл spec/mailer_spec_helper.rb:
1 2 3 4 5 6 7 8 9 | require File.dirname(__FILE__) + '/spec_helper.rb' module MailerSpecHelper private def read_fixture(action) IO.readlines("#{FIXTURES_PATH}/mailers/user_mailer/#{action}") end end |
Теперь нам нужно создать фикстуры для мейлеров в spec/fixtures/mailers, каждый мейлер в отдельном подкаталоге , например spec/fixtures/mailers/some_mailer/activation:
1 | Hello, Bob |
В spec/models/mailers/some_mailer_spec.rb напишем следующее:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | require File.dirname(__FILE__) + '/../../mailer_spec_helper.rb' context 'The SomeMailer mailer' do FIXTURES_PATH = File.dirname(__FILE__) + '/../../fixtures' CHARSET = 'utf-8' fixtures :users include MailerSpecHelper include ActionMailer::Quoting setup do # You don't need these lines while you are using create_ instead of deliver_ #ActionMailer::Base.delivery_method = :test #ActionMailer::Base.perform_deliveries = true #ActionMailer::Base.deliveries = [] @expected = TMail::Mail.new @expected.set_content_type 'text', 'plain', { 'charset' => CHARSET } @expected.mime_version = '1.0' end specify 'should send activation email' do @expected.subject = 'Account activation' @expected.body = read_fixture('activation') @expected.from = 'no-email@example.com' @expected.to = users(:bob).email Mailers::UserMailer.create_activation(users(:bob)).encoded.should == @expected.encoded end end |
Это почти все. Мы полностью уверены в том, что письма выглядят так, как ожидалось. В контроллере мы не должны повторно тестировать мейлеры, нужно всего лишь убедиться в том, что мейлеры вызываются!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | context 'Given an signup action of UserController' do controller_name 'user' setup do @user = mock('user') @valid_user_params = { :email => 'some@example.com' } end specify 'should deliver activation email to newly created user' do User.should_receive(:new).with(@valid_user_params).and_return(@user) Mailers::UserMailer.should_receive(:deliver_activation).with(@user) post :signup, :user => @valid_user_params response.should redirect_to(user_activate_url) end end |

I’m just learning rspec and despite the now old syntax it was still very helpful. Big thanks!
Thanks a lot, Dmytro! Very helpful and shot-to-the-point article.
Thanks for the tutorial. I’d like if you could post another example using mocking and stubbing instead of fixtures.