2017-08-03 34 views
1

我正在嘗試編寫一個基本的單元測試以使用下面的函數,但無法使其工作。我如何測試像返回適當的npm-express響應?如何正確地測試返回Mongoose查詢作爲Promise的函數

我已經看過Using Sinon to stub chained Mongoose calls,https://codeutopia.net/blog/2016/06/10/mongoose-models-and-unit-tests-the-definitive-guide/Unit Test with Mongoose,但仍然無法弄清楚。我目前最好的猜測,以及由此產生的錯誤,低於要測試的功能。如果可能的話,我不想使用除摩卡,錫諾和柴等以外的任何東西(即不是sin-m,cha cha cha cha cha,,等)。任何其他建議,比如我能/應該在這裏測試什麼,都是受歡迎的。謝謝!

的功能進行測試:

function testGetOneProfile(user_id, res) { 
    Profiles 
    .findOne(user_id) 
    .exec() 
    .then((profile) => { 
     let name = profile.user_name, 
     skills = profile.skills.join('\n'), 
     data = { 'name': name, 'skills': skills }; 
     return res 
     .status(200) 
     .send(data); 
    }) 
    .catch((err) => console.log('Error:', err)); 
} 

我的當前最佳猜測單元測試:

const mongoose = require('mongoose'), 
     sinon = require('sinon'), 
     chai  = require('chai'), 
     expect = chai.expect, 
     Profile = require('../models/profileModel'), 
     foo  = require('../bin/foo'); 

mongoose.Promise = global.Promise; 

describe('testGetOneProfile', function() { 
    beforeEach(function() { 
    sinon.stub(Profile, 'findOne'); 
    }); 
    afterEach(function() { 
    Profile.findOne.restore(); 
    }); 

    it('should send a response', function() { 
    let mock_user_id = 'U5YEHNYBS'; 
    let expectedModel = { 
     user_id: 'U5YEHNYBS', 
     user_name: 'gus', 
     skills: [ 'JavaScript', 'Node.js', 'Java', 'Fitness', 'Riding', 'backend'] 
    }; 
    let expectedResponse = { 
     'name': 'gus', 
     'skills': 'JavaScript, Node.js, Java, Fitness, Riding, backend' 
    }; 
    let res = { 
     send: sinon.stub(), 
     status: sinon.stub() 
    }; 
    sinon.stub(mongoose.Query.prototype, 'exec').yields(null, expectedResponse); 
    Profile.findOne.returns(expectedModel); 

    foo.testGetOneProfile(mock_user_id, res); 

    sinon.assert.calledWith(res.send, expectedResponse); 
    }); 
}); 

測試消息:

1) testGetOneProfile should send a response: 
    TypeError: Profiles.findOne(...).exec is not a function 
     at Object.testGetOneProfile (bin\foo.js:187:10) 
     at Context.<anonymous> (test\foo.test.js:99:12) 
+0

您需要檢查您的'Profile'模塊中是否定義了函數'findOne'。例如,您可能已將其定義爲「findone」。 – Mekicha

+0

從文檔:'var stub = sinon.stub(object,「method」);' 用存根函數替換'object.method'。如果該屬性不是一個函數,則會引發異常。 – Mekicha

+0

@Mekicha函數'findOne'在'mongoose'上定義,所以它應該從我的'Profile'模塊中委託。問題(我認爲!)與承諾結構有關。錯誤被拋出在'exec()'上,而不是在'findOne'上。任何其他想法? –

回答

2

這有點一個棘手的場景。這裏的問題是,測試中的findOne存根返回模型對象 - 相反,它需要返回一個包含屬性exec的對象,該對象又是承諾返回函數,最終解析爲模型值...是的,如前所述,這是一個有點棘手:)

事情是這樣的:

const findOneResult = { 
    exec: sinon.stub().resolves(expectedModel) 
} 

Profile.findOne.returns(findOneResult); 

你還需要有響應對象上status函數返回包含send功能

//if we set up the stub to return the res object 
//it returns the necessary func 
res.status.returns(res); 
對象

我認爲你不需要改變測試中的其他任何東西,它可能會這樣工作。請注意,您使用sinon 2.0或更高版本的解決方案功能存在於存根上(或者您可以使用sinon-x答應的sinon-1.x)

這篇文章詳細介紹瞭如何處理像這樣的複雜對象: https://codeutopia.net/blog/2016/05/23/sinon-js-quick-tip-how-to-stubmock-complex-objects-such-as-dom-objects/

+0

這解決了最初的問題,但現在我無法弄清楚如何存儲(或?)Express'res'對象。我可以存留'res.send(200)',但不能存儲後續的.send(data)'部分。 'return'語句拋出一個錯誤:'Error:TypeError:res.status(...)。send不是一個函數'你鏈接的帖子是內容豐富的,但我仍然卡住! –

+0

@PeterMartinson這是一個類似的問題 - res.status函數需要返回一個包含'send'函數的對象。我已經爲此更新了答案 –

相關問題