2017-03-04 79 views
1

調用私有函數單元測試模塊,我是新來的節點單元測試,撞上了路障,當涉及到承諾。我的模塊通過ApiController執行搜索,然後返回一個promise。根據其解析狀態,它會調用模塊中的兩個私有函數中的一個。是在承諾的決心

模塊:

module.exports.process = function(req, res) { 
    let searchTerm = req.query.searchValue; 

    ApiController.fetchResults(searchTerm) 
    .then((results) => onReturnedResults(results), (err) => onNoResults()); 

    function onReturnedResults(results) { 
    req.app.set('searchResults', results); 
    res.redirect('/results'); 
    } 

    function onNoResults() { 
    res.render('search/search', { noResultsFound: true }); 
    } 
}; 

測試:

var res = { 
    viewName: '', data : {}, 
    render: function(view, viewData) { 
    this.view = view; 
    this.viewData = viewData; 
    } 
}; 

var req = { query: { searchValue: 'doesnotexist' } } 

describe('When searching for results that do not exist', function() { 
    it('should display a no results found message', function(done) { 
    let expectedResult = { 
     noResultsFound: true; 
    } 

    SearchController.process(req, res); 

    // Assert... 
    expect(res.viewData).to.be.equal(expectedResult); 
    done(); 
    }); 
}) 

什麼是解決這個問題的最佳做法,我怎麼能「模擬」的fetchResults返回的承諾,這樣它實際上並沒有從取結果API(同時仍然調用私有函數)?

回答

1

如果方法程序爲關閉或者私有的模塊,那麼有沒有方法來訪問他們,只能間接驗證。爲了提供fetchResults的測試實現,它必須以某種方式公開。

一種方法是對requireApiController(這可能已經發生),然後使用proxyquiremockery覆蓋依賴關係。我與許多測試套件,誰是隻進行互動,並通過補丁require提供測試依賴關係的方式工作。測試套件成爲使用這種方法的噩夢。清理,unpatching,層疊補丁,都成爲巨大的時間黑洞,並會建議反對,如果有任何其他選項。

另一種方式是在改變fetchResults落實到你的物體的能力進行烘烤。除了測試,使得fetchResults配置將有助於從隔離未來變化的代碼,通過幫助儘量不影響process當/如果你需要獲取業績的變化方式:

var Results = (function() { 
    return { 
    process: function(req, res) { 
     let searchTerm = req.query.searchValue; 

     this.fetchResults(searchTerm) 
     .then((results) => this.onReturnedResults(req, res, results), (err) => this.onNoResults(res)), 

    fetchResults: ApiController.fetchResults,  

    onReturnedResults: function(req, res, results) { 
     req.app.set('searchResults', results); 
     res.redirect('/results'); 
    }, 

    onNoResults: function(res) { 
     res.render('search/search', { noResultsFound: true }); 
    } 
    }; 

})() 

(我沒用過JavaScript的一段時間,所以我不知道對上述對象模型的最佳方式,但重要的部分是,如果你的測試要重寫不是實現的實現已經被曝光,這上面的代碼應該做的)

現在有一個結果對象,其中fetchResults方法以易於重寫的方式公開

var fakeFetchResults = sinon.stub(); 
fakeFetchResults.return(aFakePromiseWithResultsToTriggerResultsCodePath); 
Results.fetchResult = fakeFetchResults; 

上面公開了返回函數和錯誤函數,它們也允許對該函數進行單獨的單元測試。

使用過程通過結果對象來完成,您的控制器可以註冊

Results.process

+0

謝謝,這是真正的幫助:) – tctc91