[test] 單元測試的好幫手 rewire,讓你更容易測試 private 方法及變數

前一陣子在寫單元測試(unit test)時,遇到一些問題,經過同事的提點,看到了 rewire 這個 github repo


當在寫測試時,我們可能會分許多檔案去管理我們的模組,然而模組內可能有一些 private 的方法,這時候如果想測試模組內的 private 方法該如何測試呢?

以往可能的作法: 設定環境變數(例如:test: true),在測試環境時才 export prviate 方法。

但 rewire 這個 npm package 提供一層更方便測試 private 的方法。

接下來看看實際用法吧~


比如我們有 test.js

function add(a, b) {

    return a+b;

}

function addExpression(a, b) {
    return a + ' + ' + b + ' = ' + add(a,b);
}

module.exports = {
    add: addExpression
};

index.js 則會 require('test.js'); 這個模組

var test = require('./test.js');
console.log(test.add(1,2));

當我們要寫 unit test 時會發現 test.js 的 add() 因為沒有 export 所以無法被測試,或是當在測試 test 模組時,也沒辦法把 add 做 stub(因為 js 在 function 會是 call by value)

這時候我們可以使用 rewire 去取代 require,如下面的程式碼

var rewire = require('rewire');

var test = rewire('test.js');

console.log(test.add(1,2));    // 1 + 2 = 3

// 替換 test.add 方法(stub)

var revert = test.__set__('add', function(){ return 100; });

console.log(test.add(1,2));    // 1 + 2 = 100

// 還原 test.add 方法

revert();

// 取得 add 方法

console.log(test.__get__('add'));

上面這些例子(__set____get__ 及 revert)就是 rewire 的基本應用了,其實仔細去看一下 rewire github 的原始碼,會發現他的做法,其實就是在 rewire 檔案進來之後,多包一層 function ,並且增加 __get__ 及 __set__ …這些方法,將原來模組內 global 的變數透過這些方法去做存取。

某種程度也就是將 private 的函式 export 出來,不過正常僅會在 test 的環境及程式碼中使用 rewire,因此相對不會汙染到原來的原始碼。

 

參考資料:

https://github.com/jhnns/rewire

https://stackoverflow.com/questions/22097603/unit-testing-of-private-functions-with-mocha-and-node-js

Leave a Reply