2016-06-01 7 views
0

私はデータベース内のもののリストを取得したいユニット/統合テストを作成しようとしています。それはGETだけではありませんが、これらのテストはPOST、PUT & DELETEまで拡張する必要があります。Supertest、Mocha&Sinonでのユニットテストがタイムアウトする

私はこれまで正常に動作しているコードを、私は実際にDBからデータを取得することができますが、できるだけ早く私は、DBへの呼び出しを行うための責任がある機能、アウトモカ回

をスタブアウトしようとして

1 failing

1) /account_types GET 200 List: Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test. at null. (C:\Code\JS\general_admin_service\node_modules\mocha\lib\runnable.js:215:19)

done()コールバックが呼び出されていないことは理解していますが、コードがどこかに詰まっているため、私は間違っていることを理解していません。

私は私がどこ得るために次の参照を使用:

次のように私のコードは次のとおりです。

テスト:

'use strict'; 

var expect = require('chai').expect, 
    request = require('supertest'), 
    chance = require('chance').Chance(), 
    server = require('../server'), 
    sinon = require('sinon'), 
    select = require('../../helpers/data_access/select'); 

describe("/account_types", function() { 

    before(function(done){ 
     sinon 
      .stub(select, "query_list") 
      .returns([{id: "test"}]); 

     done(); 
    }); 

    after(function(done){ 
     select 
      .query_list 
      .restore(); 

     done(); 
    }); 

    it('GET 200 List', function (done) { 

     request(server.baseURL) 
      .get('/api/v1/account_types') 
      .set('Accept', 'application/json') 
      .expect('Content-Type', 'application/json') 
      .expect(200) 
      .end(function (err, res) { 
       /* istanbul ignore if */ 
       if (err) 
        return done(err); 

       expect(res.body).to.include.keys('result'); 
       expect(res.body.result).to.not.be.null; 
       expect(res.body.result).to.not.be.undefined; 
       expect(res.body.result).to.be.an('Array'); 
       expect(res.body.result.length).to.be.above(0); 

       //expect(select.query_list).to.have.been.calledOnce; 

       return done(); 
      }); 
    }); 

}); 

Restifyエンドポイント:

var select = require('../helpers/data_access/select') 

module.exports = function (server) { 
     var query = "..." 

     return select.query_list(res, next, db_config, query); 
    }); 
}; 

select.js:

var sql = require('mssql'); 

module.exports = { 
    query_list: function (res, next, config, sql_query) { 
     return query(res, next, config, sql_query, true); 
    }, 
    query_single: function (res, next, config, sql_query) { 
     return query(res, next, config, sql_query, false); 
    } 
}; 

function query(res, next, config, sql_query, isList) { 
    var connection = new sql.Connection(config); 

    connection.connect(function (err) { 
     if (err) { 
      return on_error(err, res); 
     } 

     var request = new sql.Request(connection); 

     request.query(sql_query, function (err, response) { 
      connection.close(); 

      if (err) { 
       return on_error(err, res); 
      } 

      if (isList) { 
       return return_list(res, response, next); 
      } else { 
       return return_single(res, response, next); 
      } 
     }); 
    }); 
} 

function on_error(error, res, next) { 
    res.status(500).send(error); 
    return next(); 
} 

function return_list(res, response, next) { 
    res.send({result: response}); 
    return next(); 
} 

function return_single(res, response, next) { 
    res.send({result: response[0]}); 
    return next(); 
} 

私が起こることを期待するものは、私はquery_list機能をスタブので、私は私が持っている期待の後console.log(res.body.result);を置くことを望むべきであるということですその代わりに、私は[{id: "test"}]の返品を見なければならないが、それは明らかにその点に達していない。

私は間違っていますか?

UPDATE:完全なselect.jsファイルを追加しました。

+0

これは、 '/ api/v1/account_types'のハンドラがどのように実装されているかによって変わるかもしれません(レスポンスが送り返されていないため、 – robertklep

+0

私は知っている限り特別なことはしていません。私は基本的にresitfyサイトの例を踏襲しています... – Ebbs

+0

'select.query_list'のどこかでコードがどのように見えるのか、レスポンスはsend(' res.send() 'やそれに類するものを使用しています)。あなたがその機能をスタブしているので、応答は送信されず、Restifyは無期限に待っています(Mochaがタイムアウトするまで)。 – robertklep

答えて

1

コメントですでに明確になっているように、深くネストされたコードをテストするのは難しいです。

通常、コールバックや約束で作業するほうが大丈夫です。そのため、アプリケーションの各部分が担当する部分を処理しますが、それほど多くはありません。したがって、ルートハンドラは応答を処理します。明らかに、データベースクエリを実行する関数のような他の関数を呼び出すことはできますが、それらの関数に応答を返す代わりに、クエリ結果とともにルートハンドラに "コールバック"するコールバックを使用します。このような

何か:このような何かをテストするためにSinonを使用しての面では

server.get('/api/v1/account_types', function(req, res, next) { 
    select.query_list(QUERY, function(err, records) { 
    if (err) return next(err); 
    res.send({ results : records }); 
    next(); 
    }); 
}); 

:それは本当に正確な実装に依存します。上記のselect.query_listの使用方法をスタブして、応答に正しいデータが含まれていることを確認する簡単な例を提供できます。

基本スタブは次のようになります。

sinon.stub(select, 'query_list').yieldsAsync(null, [ { id : 'test' } ]); 

これは何、select.query_list()がコールを取得するとき、それは(それがあるかを確認するために、各引数をチェックすることでこれを行い受ける最初のコールバックの引数を呼び出しますです関数)を引数null, [ { id : 'test' } ]で置き換えます。

ハンドラで渡されるコールバック関数の引数は、errrecordsです。したがって、これを使用してデータベースクエリを完全にスキップし、クエリがレコードの特定の配列を生成したとふりまとうことができます。

res.send()が呼び出されています(これは、最初に実行した問題です:スタブのために呼び出されなかったアプリケーションの一部で実行されていたため、 )、結果の応答データが期待どおりであれば、テストをチェックインできます。

コールスタックの関数をより深くスタブしたいが、正しいSinonツール(.yields*のように、またはスタブの代わりにスパイを使用する)を使用すると、少し複雑になる。通常は大変難しいことではない。あなたがスタブ/スパイしたい機能は、アクセス可能、つまりエクスポートされています)。

+0

Exellent answer!助けと知識共有のおかげで:) – Ebbs

関連する問題