2016-12-01 11 views
1

私の正常なシャットダウンの例があります:node.jsの正常なシャットダウン中に動作を確認するための書き込みテストはどのようにテストされますか?

function stopHandler() { 
    logger.info(`Stopping server on port ${settings.port} with pid ${process.pid} started`); 

    server.close(() => { 
    logger.info(`Server on port ${settings.port} with pid ${process.pid} stopped`); 
    process.exit(); 
    }); 

    setTimeout(() => { 
    logger.info(`Server on port ${settings.port} with pid ${process.pid} stop forcefully`); 
    process.exit(); 
    }, settings.stopTimeout); 
}; 

process.on("SIGTERM", stopHandler); 
process.on("SIGINT", stopHandler); 

私はモカと、このコードをテストするにはどうすればよいですか?

答えて

7

あなたのコードをどの程度広範囲にテストしたいのかは明らかですが、ここから始めて定型文があります。

いくつかの説明:server.close()process.exit()

  • コードは、2つの機能をスタブにしsinonを使用しています。それらをスタブすると、それらの関数を呼び出す代わりに、 "偽の関数"(スタブ)が呼び出され、が呼び出された場合はをアサートできます。
  • SIGINTテストをコメントアウトしました。これは、mochaがその信号を使用してテストランナーを中止したことがわかったためです。しかし、SIGTERMSIGINTは全く同じハンドラを使用しているので、これは問題ありません。
  • シグナル配信は非同期です。つまり、テストも非同期でなければなりません。私は、プロセスにシグナルが送られたときに呼び出される、テストされるべきシグナル用の "once"シグナルハンドラを追加しました。その時点でstopHandlerが呼び出されているはずです。アサーションを行い、最後にdoneコールバックを呼び出して、Mochaにテストが完了したことを伝えます。

コード:

const sinon = require('sinon'); 

// Load the module to test. This assumes it exports (at least) 
// `server` and `settings`, because the test needs them. 
let { server, settings } = require('./your-module'); 

// Don't call the stopHandler when exiting the test. 
after(() => { 
    process.removeAllListeners('SIGTERM'); 
    process.removeAllListeners('SIGINT'); 
}) 

describe('Signal handling',() => { 
    [ 'SIGTERM' /*, 'SIGINT' */ ].forEach(SIGNAL => { 

    describe(`${ SIGNAL }`,() => { 
     let sandbox, closeStub, exitStub; 

     beforeEach(() => { 
     sandbox = sinon.sandbox.create({ useFakeTimers : true }); 
     closeStub = sandbox.stub(server, 'close'); 
     exitStub = sandbox.stub(process, 'exit'); 
     }) 

     afterEach(() => { 
     sandbox.restore(); 
     }) 

     it(`should call 'server.close()' when receiving a ${ SIGNAL }`, done => { 
     process.once(SIGNAL,() => { 
      sinon.assert.calledOnce(closeStub); 
      done(); 
     }); 
     process.kill(process.pid, SIGNAL); 
     }) 

     it(`should call 'process.exit()' after ${ settings.stopTimeout } seconds when receiving a ${ SIGNAL }`, done => { 
     process.once(SIGNAL,() => { 
      // It shouldn't have called `process.exit()` right after the signal was sent. 
      sinon.assert.notCalled(exitStub); 

      // Advance the clock to a bit after the timeout. 
      sandbox.clock.tick(settings.stopTimeout + 10); 

      // At this point, the timeout handler should have triggered, and 
      // `process.exit()` should have been called. 
      sinon.assert.calledOnce(exitStub); 

      // Done. 
      done(); 
     }); 
     process.kill(process.pid, SIGNAL); 
     }) 

    }) 

    }) 

}) 
+0

これは、共有のためのおかげで本当に良いテストです。素晴らしい答え。 –

関連する問題