私は、回避しようとしている高価なネットワーク呼び出しとのインターフェースを低レベルで行うフルスタック受け入れテストを作成する方法について少し困惑しています。
私はrspecとcucumberを使用しており、モックのほとんどをrspeckモックで行っています。
以下は、私がテストしているもののコンテキストを説明するために私が行っていることの不自然な例です。
後でレシピなどを作成できる材料を追加するためのページがあります。新しい材料の作成が成功すると、材料モデルはWebサービスにアクセスして、特定の食品に関するusda栄養情報を取得し、材料モデルに保存します。
食品の名前を取得し、Webサービスを介して適切な要求を行い、xml応答を返すWebServiceInterfaceクラスを作成しました。次に、別のヘルパークラスがxml応答を解析し、栄養情報のコレクションを返します。このコレクションは、成分インスタンスで使用されます。
今、私はすでにWebServiceInterfaceを実行する一連の単体テストを作成しました。こんな感じ
fake-webservice = double('WebserviceInterface')
fake-webservice.should_receive(:get_response_xml).with(ingredient).and_return(fake_xml_response)
result = ResponseParser.new(fake-webservice).get_ingredient_nutritional_info
result.calories.should eql(123)
result.saturated_fat.should eql(10)
get_response_xml
これは、応答パーサーによって内部的に呼び出されることに注意してください。この場合、ResponseParserはget_response_xml
注入されたでを呼び出しますfake-webservice
。
モデルの場合、それはうまく機能し、ダンディですが、受け入れテストでは状況はより複雑です。「新しい材料の作成」ページ(new_ingredient_path
)と、すべての材料とその栄養情報を一覧表示する材料インデックスパス()の統合をテストするページの検収テストを作成したいと思いますingredients_path
。
検収試験は次のようになります。
visit new_ingredient_path
fill_in 'ingredient_name' :with => 'pickled herring'
click_button 'Create ingredient'
visit ingredients_path
page.should have_content 'Pickled Herring 123 calories 10g saturated fat'
冗長なコンテキストはさておき、これが質問です。実際のWebサービスがプロセスで呼び出されないようにしながら、このタイプの受け入れテストを作成するための最良の方法は何ですか。
サービスはリクエストごとに課金され、私は多くのテストを行うため、この状況では「統合/受け入れテストですべての相互作用を実際にテストする必要があります」では不十分です。
テスト環境で実際のWebサービスの代わりに偽のWebサービスなどが使用されていることを確認する方法を見つける必要があります(おそらく開発でも?)。.Netのバックグラウンドから来て、私が聞き慣れている典型的な答えは「依存性注入を使用する!!?!!」です。DIにはメリットがあると思いますが(これをDIの議論に変えないでください)、ここにはもっと単純で軽量なソリューションがあると思います。
If ENV["RAILS_ENV"] == 'test'
私はそれから偽物を使うようなことをすることを考えました、さもなければ本物のものを使います。これは、レール環境で一般的に使用されるイディオムですか、それとも粘着性が高すぎますか?
これを、たとえば「spec_helper.rb」ブロックまたはキュウリfeatures / support / env.rbブロックで構成できるプロバイダーのタイプとして登録する方法はありますか?
考え、アイデア、インプット、アドバイス???? Rails開発者を体験できますか?および/またはCucumber/Rspecの第一人者は、このタイプのテストを実行するための一般的な方法を教えてください。