2016-08-25 32 views
0

我目前使用摩卡2.5.3,supertest 2.0.0,knex 0.11.10,restify 4.1.1和sqlite3 3.1.4。爲什麼摩卡超時與restify和knex一起使用?

我有以下非常簡單的RESTify服務器:

const restify = require('restify'); 
const knex = require('knex')({ 
    client: 'sqlite3', 
    connection: { 
    'filename': 'test.db' 
    } 
}); 

const app = restify.createServer(); 

app.get('/', (req, res, next) => { 
    knex.select().from('nonexistent_table') 
    .then((rows) => { 
    return res.json(rows); 
    }) 
    .catch((err) => { 
    return res.send('error'); 
    }); 
}); 
module.exports = app; 

下面的測試將導致測試在2000毫秒超時失敗的,而不是:

const assert = require('assert'); 
const supertest = require('supertest'); 
const app = require('./app'); 

describe('GET /', function() { 

    it('should not timeout', function (done) { 
    supertest(app) 
    .get('/') 
    .end(function(err, res) { 
     assert(false); 
     done(); 
    }); 
    }); 
}); 

如果到knex呼叫,而不是滿足被拒絕,測試失敗並且沒有超時。只有當knex呼叫被拒絕時,超時纔會出現。

有沒有人有想過什麼可能導致超時而不是適當的失敗?

編輯:我已經儘可能地調試了它,似乎摩卡時嘗試生成堆棧跟蹤發生超時。

+0

查看我的回答[here](http://stackoverflow.com/a/39103469/893780):因爲斷言拋出一個錯誤,'done'永遠不會被調用_and_錯誤永遠不會被捕獲。 – robertklep

+1

@robertklep謝謝,但我不確定這是正確的答案有兩個原因。首先,如果knex解析,測試正常失敗。由於我在測試中做了一個「assert(false)」,所以失敗的模式根本不應該取決於restify服務器的響應或knex的結果,但不知何故它確實!其次,如果我編寫一個不做異步http調用的mocha測試,並且只是拋出一個錯誤,那麼即使我從不調用'done()',測試也會失敗並且不會超時。這使我相信拋出錯誤/失敗斷言是摩卡測試失敗的正常方式。 – harrymonster

回答

0

試圖改變第一行以: bluebird.resolve(knex.select().from('nonexistent_table'))

還需要需要在上面「藍鳥」。這將解決問題的給你一個錯誤

一些方面,我認爲這個問題與選擇:你忘了一個參數

+0

剛剛嘗試了這兩種潛在的解決方案,但他們沒有解決問題。也就是說,我試着從'('nonexistent_table')''嘗試'knex.select('*')。我也嘗試過''('nonexistent_table'))'bluebird.resolve(knex.select('*'))。 – harrymonster

1

supertest使用superagent幕後superagent支持的承諾。 (搜索.thenhere。)所以你可以使用.then代替.end和剛剛回歸的承諾,而不是使用done的:

it('should not timeout', function() { 
     return supertest(app) 
      .get('/') 
      .then(function(res) { 
       assert(false); 
      }); 
    }); 

當我用你的代碼的問題,其餘上面的代碼,然後我得到適當的失敗。

至於爲什麼使用done不起作用,我不明白。 supertestsuperagent可能會吞入傳遞給.end()的回調中引發的異常。如果異常被吞噬,那麼Mocha無法檢測到它們。然後你必須自己去捕捉失敗斷言引發的異常,並將它們傳遞給done。我更願意使用承諾。

+0

我的猜測是,在失敗的情況下,'end'回調是從_inside_路由處理程序中的'.catch()'調用的,它將吞噬斷言錯誤_and_阻止'done'被調用。 – robertklep

+0

我同意承諾可能是正確的方向去這裏。但是我開始認爲這可能是節點中的一個bug,因爲如果我在'.end()'回調中引發異常,但是knex在服務器端沒有被調用,那麼測試通常會失敗。這對我說,超級好戰者並沒有吞噬例外。還有其他一些事情正在發生,我認爲這與mocha生成堆棧跟蹤有關。我會用我的發現來更新我的問題。 – harrymonster

+0

另一個理論是,因爲'catch'不會發送錯誤響應,所以一些內部的'superagent' promise可能會被解決,所以隨後的斷言失敗不能再拒絕它。 – robertklep