簡體   English   中英

使用 rails mailer 參數化時如何最好地使用 rspec 模擬

[英]How to best use rspec mocks when using rails mailer parameterization

我目前正在更改我們的 rails 郵件程序以使用使用參數化的郵件程序的更新方式,這使我們的代碼庫與rails guide內聯,但更重要的是它還允許在日志和第 3 方中適當過濾參數AppSignal 等應用程序。

IE。 我正在改變這個

UserMailer.new_user_email(user).deliver_later

UserMailer.with(user: user).new_user_email.deliver_later

但是我們有很多規范使用 Rspec Mocks 來確認使用適當的參數調用了郵件程序。 通常,這些測試控制器實際上要求郵件發送者正確使用電子郵件。

我們一般有這樣的:

        expect(UserMailer).to receive(:new_user_email)
                                .with(user)
                                .and_return(OpenStruct.new(deliver_later: true))
                                .once

但是現在有了郵件程序的參數化,我看不到任何簡單的方法來使用 rspec 模擬來驗證是否使用正確的參數調用了正確的郵件程序方法。 有人對現在如何最好地進行測試有任何想法嗎? 期望的可讀性可能是這里最大的因素,理想情況下它是一行沒有多行模擬設置。

注意:我真的不想實際運行郵件程序,我們有郵件程序單元規格來測試實際郵件程序是否正常工作。

當您有幾個鏈接的方法時,您可以使用receive_message_chain但是有一個回撤-它不支持計數器的整個流暢界面,例如once twice

所以你必須在這里做一個技巧:

# set counter manually
counter = 0

expect(UserMailer).to receive_message_chain(
  :with, :new_user_email
).with(user: user).with(no_args).and_return(OpenStruct.new(deliver_later: true)) do
  counter += 1
end

# Very important: Here must be call of your method which triggers `UserMailer` mailer. For example
UserNotifier.notify_user(user)

expect(counter).to eq(1)
# class for example
class UserNotifier
  def self.notify_user(user)
    UserMailer.with(user: user).new_user_email.deliver_later
  end
end

因此,對於將來遇到此問題的其他任何人。 我最終在 specs/support 目錄中添加了一個輔助方法,如下所示

def expect_mailer_call(mailer, action, params, delivery_method = :deliver_later)
  mailer_double = instance_double(mailer)
  message_delivery_double = instance_double(ActionMailer::MessageDelivery)
  expect(mailer).to receive(:with).with(params).and_return(mailer_double)
  expect(mailer_double).to receive(action).with(no_args).and_return(message_delivery_double)
  expect(message_delivery_double).to receive(delivery_method).once
end

然后可以在這樣的規范中調用

expect_mailer_call(UserMailer, :new_user_email, { to:'email@email.com', name: kind_of(String) })

或為 Deliver_now

expect_mailer_call(UserMailer, :new_user_email, { to:'email@email.com', name: kind_of(String) }, :deliver_now)

它適用於我們的情況,但如果您需要配置一次限制,您可能需要對其進行調整並添加部分電子郵件或其他內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM