2016-01-03 14 views
10

gulp-jsx-coveragegulp-mochamochaを使用してテストスイートを実行しています。私のテストはすべて実行され、合格/不合格になります。しかし、テストされているモジュールの中には、superagentライブラリ経由でAPIにHTTPリクエストを送信するものがあります。APIに接続しようとすると、Mochaテストスイートでエラーが発生する

開発中の私は、クライアント側のアプリケーションと一緒にlocalhost:3000にAPIを実行しています。クライアント側のテストでアクセスしようとしているURLです。ただし、テストする場合、APIは通常実行されません。これは、次のエラーで要求が通過取得する任意の時間を結果:

Error in plugin 'gulp-mocha' 
Message: 
    connect ECONNREFUSED 
Details: 
    code: ECONNREFUSED 
    errno: ECONNREFUSED 
    syscall: connect 
    domainEmitter: [object Object] 
    domain: [object Object] 
    domainThrown: false 
Stack: 
Error: connect ECONNREFUSED 
    at exports._errnoException (util.js:746:11) 
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:983:19) 

私はそうのように、グローバルヘルパーに(requestとしてエイリアス)superagent上のすべてのメソッドをスタブライブラリを試してみた:

function httpStub() { 
    return { 
    withCredentials:() => { 
     return { end:() => {} }; 
    } 
    }; 
}; 

beforeEach(function() { 
    global.sandbox = sinon.sandbox.create(); 

    global.getStub = global.sandbox.stub(request, 'get', httpStub); 
    global.putStub = global.sandbox.stub(request, 'put', httpStub); 
    global.patchStub = global.sandbox.stub(request, 'patch', httpStub); 
    global.postStub = global.sandbox.stub(request, 'post', httpStub); 
    global.delStub = global.sandbox.stub(request, 'del', httpStub); 
}); 

afterEach(function() { 
    global.sandbox.restore(); 
}); 

何らかの理由でテストに遭遇したときにメソッドがスタブされないため、ECONNREFUSEDエラーに達します。私は三重チェックして、どこに私はサンドボックスやスタブを復元しています。

私が実行している問題を解決する方法か、この全体的な解決策がありますか?

+0

を助けるべきである。このような

何か挙動が決定論的ですか?あなたは問題が「いくつかのテスト」のために発生すると書いています - それは常に失敗した同じテストセットか、特定のテストが1回のテストランで合格し、他のテストで失敗することでしょうか?それは同じテストで毎回失敗しませんが、それはテストの特定のサブセット内の失敗しない@TomasKulich –

+0

。これは、これらのアクションが最終的にAPIへの呼び出しをもたらすテストであるからです。私が以前にエラーが出た単一のテストファイルを実行すると、それは成功します。これはおそらく 'request'メソッドが何らかの理由でunstubbedになっているために、スイート全体を実行しているようだと思われます。 – Jakemmarsh

答えて

4

問題は、テストで非同期のものを正しく実行しないことが原因である可能性があります。次の例を想像:

it('is BAD asynchronous test',() => { 
    do_something() 
    do_something_else() 
    return do_something_async(/* callback */() => { 
    problematic_call() 
    }) 
}) 

モカは、それが(同期)do_somethingdo_something_elsedo_something_asyncを実行するような試験を発見します。その瞬間、Mochasの視点からテストは終わり、MochaはafterEach()を実行します(悪いのは、まだproblematic_callです)!(さらに悪いのは何ですか?)次のテストを開始します!

明らかに、並行してテスト(beforeEachとafterEach)を実行すると、実際には奇妙で予測不可能な結果につながる可能性があるので、何か間違っていることは驚きではありません。テストが終了したときに

は常に、モカに知らせる:それを行うにはどのような環境)

をunstubbing。テストが終了するだけにして、それは次のテストを実行するときモカが「知っている」この方法

it('is BAD asynchronous test', (done) => { 
    do_something() 
    do_something_else() 
    return do_something_async(/* callback */() => { 
    problematic_call() 
    done() 
    }) 
}) 

https://mochajs.org/

:これはdoneコールバックを呼び出すことにより、プロミスオブジェクトを返すのいずれかによって行われ、またはすることができます。

+0

これは本当にあなたの問題ですが、あなたはまだそれをデバッグするのは難しいかもしれません - omg omg where callback /私は待っていないと約束します。これが当てはまる場合は、私が使用できる便利なトリックを書きません。 –

+0

あなたが正しいと思われます。私は、非同期テストのための 'done'コールバックを知っていたと私はそれがどこでも必要な使用していたと思ったが、それは同様にasyncを指定するために必要な、私の他のテストのいくつかを判明しました。いくつかの壊れたテストを修正することは、 '要求 'でそれらの醜いグローバルスタブを取り除くことができ、関連するテストではスタブだけを取り除くことを意味しました。ありがとう! – Jakemmarsh

+0

パーフェクト、私はそれが助けてうれしいです。また、非同期関数のかなり良いオプションはPromiseオブジェクトを返すことです(しかし、Promisesを適切に連鎖させる必要があります)。 –

1

requestは既にアプリケーションで必要とされているため、テストでスタブを使用するかどうかは関係ありません。

rewireのようなものを使用し、アプリケーションで必要とされるrequestをスタブ付きのバージョンに置き換える必要があります。

var request = require('superagent'), 
    rewire = require('rewire'), 
    sinon = require('sinon'), 
    application = rewire('your-app'), 
    rewiredRequest; 

function httpStub() { 
    return { 
     withCredentials:() => { 
      return { end:() => {} }; 
     } 
    }; 
}; 

beforeEach(function() { 
    var requestStub = { 
     get: httpStub, 
     put: httpStub, 
     patch: httpStub, 
     post: httpStub, 
     del: httpStub 
    }; 

    // rewiredRequest is a function that will revert the rewiring 
    rewiredRequest = application.__set__({ 
     request: requestStub 
    }); 
}); 

afterEach(function() { 
    rewiredRequest(); 
}); 
関連する問題