サードパーティのメーラーを使用したRails TDD?
-
28-10-2019 - |
質問
Twilio SMS APIを実装しているRailsアプリケーションがあり、デザインのテスト方法について少し迷っています。
開始するために、Twilio APIをカプセル化するSMSメーラーであるモデルを作成しました。SMSクレジットを使用したり、テストテキストメッセージを使用して誰かを攻撃したりせずにテストして機能を確保できるようにしたいと考えています。
私はAPIを実装し、コードで動作させる方法を知っていますが、私が助けが必要なのは、実際にコードをテストして、それが機能し、将来の破損を防ぐことです。誰かがアドバイスを提供できますか?
ありがとう!
解決
テストとテストのTwilioアプリケーションの私の経験は、あなたが 追加するリスクを排除するためのテスト. 。使用したいと思うでしょう Twilio Gem 自分のSMSコードをRESTエンドポイントに巻き込むのではなく、リスクの量を最小限に抑えます。
APIをビジネスロジッククラスでできるだけ薄く包み、主にビジネスロジックをテストします。たとえば、私のシステムでは、SMSEはリマインダークラスから送信されます。コードは次のようになります:
class SomeWrapperClass
if (RAILS_ENV == "testing")
@@sent_smses = []
cattr_accessor :sent_smses
end
def send_a_message(to, from, message, callback_url = nil)
unless RAILS_ENV == "testing"
Twilio::SMS.message(to, from, message, callback_url)
else
@@sent_smses << {:to => to, :from => from, :message => message, :callback_url => callback_url}
end
end
end
これにより、私のビジネスロジックに焦点を当てたテストを書くことができます。これは私が台無しにするものです。たとえば、SMSメッセージを送信するメソッドsend_reminder(クライアント)をテストする場合:
test "sends reminder to client" do
SomeWrapperClass.sent_smses = []
client = clients(:send_reminder_test_case)
Reminder.send_reminder(client)
sent_message = SomeWrapperClass.sent_smses.last
assert !sent_message.blank?, "Sending a reminder should fire an SMS to client."
assert sent_message.index(client.name) >= 0, "Sending a reminder should fire an SMS with the client's name in it.
...
end
今、私は追加した実際のリスクをテストしています。つまり、Reminder.send_reminderを台無しにしています。一方、ラッパーはリスクのないものに近い必要があります。
他のヒント
私のgem twilio.rbを使用して、すでにテストされています。たとえば、Mochaを使用してテストでock笑することができます。
Twilio::SMS.expects(:create).with :to => '+19175551234', :from => '+12125551234', :body => 'this is easy!'
ユニットテストは、外部サービスに衝突することは決してなく、常にock笑する必要があります。これは、テストがテストされているオブジェクトのクラス境界を拡張してはならず、コラボレーターオブジェクトをmocked/stabledにする必要がないという単体テストの一般的な原則から続きます。
お役に立てれば!
可能な限り多くのロジックを明らかに分離します。これを行うことで、可能な限り他のすべてをテストし、その後、テストが必要な外部APIに電話のみを残すことができます。
外部APIを使用するのは難しい場合があります。 1つの選択肢は、あなたがあなたのために働くことや、あなたが期待する応答に役立つことに対する応答をock笑することです。これは明らかに少し脆弱です。別のオプションは、ようなものを見ることです VCR. 。これにより、外部APIへの呼び出しが一度記録され、再び電話をかけるたびに再び再生します。
この男はあなたの問題を解決し始めたようです: https://github.com/arfrank/fake-twilio-api
おそらくTwiliolibのコードをテストする必要はありませんが、Twiliolibのメソッドをスタブしたくない場合は、特定のリクエストの応答を定義するFakeWeb GEMを使用できます。
言及されたスティーブと同様に、私はMochaでリクエストを突き刺すだけです:
# In Twilio initializer
TWILIO_ACCOUNT = Twilio::RestAccount.new(TWILIO_CONFIG[:sid], TWILIO_CONFIG[:token])
# In a test helper file somewhere
class ActiveSupport::TestCase
# Call this whenever you need to test twilio requests
def stub_twilio_requests
# Stub the actual request to Twilio
TWILIO_ACCOUNT.stubs(:request).returns(Net::HTTPSuccess.new(nil, nil, nil).tap { |n|
n.stubs(:body).returns("<?xml version=\"1.0\"?>\n<TwilioResponse></TwilioResponse>\n")
})
end
end