2012-06-05 3 views
3

У меня есть тест RSpec так:Используя RSpec для тестирования ActionMailer с should_receive

it "should ..." do 
    # mailer = mock 
    # mailer.should_receive(:deliver) 
    Mailer.should_receive(:notification_to_sender)#.and_return(mailer) 

    visit transactions_path 
    expect do 
    page.should_not have_css("table#transactions_list tbody tr") 
    find('#some_button').click 
    page.should have_css("table#transactions_list tbody tr", :count => 1) 
    end.to change{Transaction.count}.by(1) 
end 

Если удалить закомментированные части в верхней части, проходит тест. Но с комментариями разделов (как я ожидал бы написать это) тест не удался.

Я получил комментарии от некоторых поисковых систем по сети, но я действительно не понимаю, что он делает или почему это исправляет. Кажется, должен быть более чистый способ проверить электронные письма без этого.

Может ли кто-нибудь пролить свет? Благодаря!

Я использую рельсы 3 и RSpec-рельсы 2.10.1

ответ

2

Я думаю, что вы хотите экземпляр Мейлер получить notification_to_sender не класс. Из Rails API

Вы никогда не создаете экземпляр своего класса почтовой программы. Скорее, методы экземпляра доставки автоматически завертываются в методы класса, которые начинаются со слова deliver_, за которым следует имя метода почтовой программы, который вы хотите отправить. Метод signup_notification, определенный выше, доставляется путем вызова Notifier.deliver_signup_notification.

Поэтому я хотел бы использовать

Mailer.any_instance.should_receive(:notification_to_sender) 

Кроме того, если вам нужно, чтобы получить последний доставленное сообщение, используйте

ActionMailer::Base.deliveries.last 

Я думаю, что должно решить вашу проблему.

+0

hmm, я не уверен, почему, но все равно кажется, что это не сработало:/показанная ошибка не имеет смысла (из другой строки), но когда я прокомментирую строку should_receive, она снова работает. О, хорошо ... теперь на большие проблемы. –

+0

API ActionMailer фактически изменился с «Mailer.deliver_notification_to_sender» в Rails 2.x на «Mailer.notification_to_sender.deliver» в Rails 3.0. Учитывая это изменение, методы экземпляра доставки больше не завертываются в методы класса, так как без доставки вызова вы возвращаете экземпляр «Mail :: Message» – MAP

+0

В конечном итоге это решило мои проблемы с DelayedMailer, спасибо –

2

Возможно, вы звоните Mailer.notification_to_sender.deliver в свой контроллер или, еще лучше, фоновое задание. Я предполагаю, что notification_to_sender также принимает параметр.

В любом случае, когда вы вызываете метод notification_to_sender на Mailer, вы возвращаете экземпляр Mail::Message, на котором есть метод deliver. Если вы просто делали Mailer.notification_to_sender без звонка deliver, вы могли бы запустить то, что у вас там есть, и все будет хорошо. Я бы предположил, что вы также звоните deliver.

В этом случае ваше сообщение об ошибке будет что-то вроде

NoMethodError: 
    undefined method `deliver' for nil:NilClass 

Это потому, что nil это возвращаемое значение по умолчанию в Ruby большую часть времени, которое Rails также наследует. Без указания частей mailer = mock и .and_return(mailer), когда контроллер выполняет в контексте теста, уведомление__использует nil, и контроллер попытается вызвать deliver на этом объекте nil.

Решение, которое вы закомментировали, состоит в том, чтобы выкачать возвращаемое значение notification_to_sender (обычно Mail::Message), а затем ожидать, что на него будет вызван метод deliver.

Смежные вопросы