文章翻譯自How to Mock an Express sessionhtml
你是否正在使用Express框架?你是否是正在作服務端的集成測試(end-to-end)?這裏我將討論在項目中遇到的問題。這篇文章涵蓋了我在使用Express框架作集成測試時所遇到的挑戰,以及我是如何尋找技術解決方案的。node
當你也遇到相同的問題時,但願這篇文章對你有所幫助。express
我作的項目是先要向amazon s3批量上傳圖片文件,而後對這些文件作一些裁剪、壓縮和編輯的任務。npm
使用Express中間件作認證、受權以及設置上下文的工做都很順利。我使用cookie-session做爲控制session的中間件,這就意味着須要cookie-session負責相應session數據的加密、配置和解密。api
我知道許多開發者使用sinon for unit testing。若是你對它不熟悉,我先簡短介紹下它:sinon for unit testing是經過Javascript的測試框架(如mocha)來實現mock的方法。可是問題來了,若是要實現Express Session的mock測試?在Express中有沒有實現mock session的解決方案?bash
下面我將講述我所遇到的挑戰。我有兩個路由,一個是向s3上傳圖片的、另外一個是對上傳圖片作一些額外處理(如壓縮、編輯)。對於第一個路由我先設置請求的session,而後再跳轉到第二個路由。cookie
1)api/image/createsession
exports.create = function(req, res) {
// upload image to s3
var photos = PhotosTable.create(req.files.names); // add entries in database
req.session.count = photos.length; // set count in req.session
res.redirect(`api/image/submit`);
}
複製代碼
exports.submit = function(req, res) {
if (req.session.count && req.session.count > 0) { // get count from req.session
// perform further tasks
res.sendStatus(200);
} else {
res.sendStatus(400);
}
}
複製代碼
我想mock第二個路由(api/image/submit)。然而問題是:(pi/image/submit)這個路由須要先覈查req.session.count,而後在繼續後面的操做。若是count是空值,迴應400。使用Mocha框架你只能mock第一個路由,不能實現下面的功能:第一個路由跳轉到第二個路由,而後程序從第二個路由向第一個路由的返回值,而後驗證第二個路由返回值的測試用例。併發
最簡單的解決方案是在測試用例中,經過req params直接請求第二個路由,而後檢查params是否存在,若是存在就取消檢查req.session.count。app
然而,這種解決方案並非最好的。由於
咱們也能夠放棄使用兩個個路由,把全部的代碼都寫在一個路由中。可是咱們真的要這麼作嗎?據我所知,不該該爲了測試用例更改代碼(one should never change implementatin for the sake of test cases)
這個問題看起來很普通,可是我在網上(至少是在StackOverFlow)上並無找到解決方案。起初我猜想在一些模塊中已經解決了這個問題,諸如mocha, 或是cookie-seeion等常常在Express中使用的模塊。
然而,並無。
在程序中我是使用cookie-session來維護Express與session間的管理工做。cookie-session經過Keygrip和Crypto來設置和驗證session的簽名。
在設置session cookies時須要name和key: name被用來做爲cookie的名字。 key是做爲Keygrip對cookie值進行簽名的概要值。
我在測試用例請求第二個路由時,設置req.session.count的值。下面就是代碼:
// name = "my-session" -> base64 value of required object (cookie)
// name.sig = "my-session.sig" -> signed value of cookie using Keygrip
let cookie = Buffer.from(JSON.stringify({"count":2})).toString('base64'); // base64 converted value of cookie
let kg = Keygrip(['testKey']) // same key as I'm using in my app let hash = kg.sign('my-session=' + cookie); await request(app).get('api/image/submit').set("Accept", "text/html") .set('cookie', ['my-session=' + cookie + '; ' + 'my-session.sig=' + hash + ';']) .expect(200); 複製代碼
這僅僅是一條mock session的測試用例。在大多數狀況下,測試用例須要定製所要測試的參數值,但這個代碼能夠設置任何你想測試的參數。
我已經建立一個Nodejs.js包併發不到npm中,經過這個包mock-session,你能夠很容易作mock session的測試。