0

私はrspecに非常に慣れていないので、作成されたオブジェクトが実際に存在することを確認するテストを作成しようとしています. 私のテストは次のようになります。

require 'spec_helper'

describe "UserService" do
  describe ".new" do
    it "should create a UserService object" do
      service = UserService.new
      service.should_not be_nil
    end
  end
end

問題は、テストを実行すると次の出力が得られることです。

  1) UserService.new should create a UserService object
     Failure/Error: service = UserService.new
     Errno::ECONNREFUSED:
       Connection refused - connect(2)
     # ./spec/requests/user_service_spec.rb:6:in `new'
     # ./spec/requests/user_service_spec.rb:6:in `block (3 levels) in <top (required)>'

この時点で接続が拒否されることを期待していますが、テストを中断するのではなく、どうすればそれをテストできますか? または、私が見ているのは正しい出力ですか? ありがとう!

4

1 に答える 1

1

これには2つの問題があります。まず、実際にテストで外部サービスに接続しようとしています。通常、テスト対象のオブジェクトに、通常接続するサービスを表すある種のモックをフィードします。あなたの質問とコメントの内容から、コードを機能させるには次の変更が必要になると推測しています。

UserService オブジェクトから実際のサービスを「隠す」には、ファサード (プロキシ) オブジェクトを作成する必要があります。そのオブジェクトは基本的に、基礎となるサービスを 1 対 1 でマッピングする必要があります。この理由は、内部を外部サービスにしっかりとバインドするのではなく、それらをオブジェクトにバインドする必要があるためです (決して厳密にはバインドしないでください)。ファサードは単体テストを行うべきではありません。これにより、現在の場所にすぐに戻ることができます。また、ビジネス ロジックが含まれていないため、単体テストを行う必要もありません。

2 つ目は、UserService オブジェクトを特定の基になるサービス実装から切り離すために、依存関係の逆転が必要なことです。UserServices コンストラクターがオブジェクト、任意のオブジェクトを取得し、そのメソッドを呼び出して、サービス関連の処理を実行する必要があります。UserService は、それが実際のサービスであるかどうか (およびすべきではない) を気にしなくなるため、テスト中に単純なスタブを供給することができ、外部サービスが遅いかダウンしている場合、またはその他の方法でテストを中断する必要はありません。予期しない動作をします。

2 つ目はshould_not raise_error、テストで特定のケースを無視していたことです。指定されたエラーで使用することはshould_not raise_error(ConnectionError)問題ありませんが、エラーをスローするのは、自分自身を救うことができない場合に行うのが通常のことであり、後でこの動​​作を追加すると、テストがクラッシュしてはならないときにテストが中断されます。

このテストでは、 を呼び出すときに UserService オブジェクトを取得する必要があるUserService.new()ことが示されていますが、次の場合に返されないことについては何も言及されていません ...次のような 2 番目のテストを作成します。

describe ".new" do
  it "when service is down should throw error" do
    UserService.new(offline_mock).should raise_error(ConnectionError)
  end
end

このような状況に陥らないようにする方法について少し考えてみます ;) いつものように、テストの問題は通常、アーキテクチャ上の問題の兆候です。

于 2013-02-06T09:27:08.763 に答える