2015-03-03 12 views
5

पर mongoose save method को दबाकर मैं मोंगोस मॉडल के लिए save विधि को स्टब करना चाहता हूं।मॉडल

/* model.js */ 
var mongoose = require('mongoose'); 
var userSchema = mongoose.Schema({ 
    username: { 
    type: String, 
    required: true 
    } 
}); 
var User = mongoose.model('User', userSchema); 
module.exports = User; 

मैं कुछ सहायक समारोह है कि save विधि कॉल होगा: यहाँ एक नमूना मॉडल है।

/* utils.js */ 
var User = require('./model'); 
module.exports = function(req, res) { 
    var username = req.body.username; 
    var user = new User({ username: username }); 
    user.save(function(err) { 
    if (err) return res.end(); 
    return res.sendStatus(201); 
    }); 
}; 

मैं जाँच करने के लिए है कि user.save एक इकाई परीक्षण का उपयोग कर मेरी सहायक समारोह के अंदर कहा जाता है चाहते हैं।

/* test.js */ 
var mongoose = require('mongoose'); 
var createUser = require('./utils'); 
var userModel = require('./model'); 

it('should do what...', function(done) { 
    var req = { username: 'Andrew' }; 
    var res = { sendStatus: sinon.stub() }; 
    var saveStub = sinon.stub(mongoose.Model.prototype, 'save'); 
    saveStub.yields(null); 

    createUser(req, res); 

    // because `save` is asynchronous, it has proven necessary to place the 
    // expectations inside a setTimeout to run in the next turn of the event loop 
    setTimeout(function() { 
    expect(saveStub.called).to.equal(true); 
    expect(res.sendStatus.called).to.equal(true); 
    done(); 
    }, 0) 
}); 

मैं here से var saveStub = sinon.stub(mongoose.Model.prototype, 'save') की खोज की।

सब ठीक है जब तक कि मैं अपने saveStub पर कुछ जोड़ने की कोशिश नहीं करता, उदा। saveStub.yields(null) के साथ। अगर मैं अनुकरण करने के लिए एक त्रुटि saveStub.yields('mock error') साथ save कॉलबैक करने के लिए पारित किया जा रहा था, मैं इस त्रुटि मिलती है:

TypeError: Attempted to wrap undefined property undefined as function 

स्टैक ट्रेस पूरी तरह से बेकार है।

अनुसंधान मैं

किया है मैं अपने मॉडल refactor करने के लिए अंतर्निहित उपयोगकर्ता मॉडल में पहुँच प्राप्त करने का प्रयास किया, सिफारिश के रूप में here। इससे मेरे लिए एक ही त्रुटि उत्पन्न हुई। यहाँ है कि प्रयास के लिए मेरे कोड था:

/* in model.js... */ 
var UserSchema = mongoose.model('User'); 
User._model = new UserSchema(); 

/* in test.js... */ 
var saveStub = sinon.stub(userModel._model, 'save'); 

मैंने पाया कि this solution बिल्कुल मेरे लिए काम नहीं किया। शायद ऐसा इसलिए है क्योंकि मैं अपने उपयोगकर्ता मॉडल को एक अलग तरीके से स्थापित कर रहा हूं?

मैंने this guide और this one के बाद मॉकरी का भी प्रयास किया है, लेकिन यह आवश्यक था कि मुझे लगता है कि यह आवश्यक होना चाहिए, और मुझे डीबी को अलग करने के लिए समय बिताने का मूल्य पूछा गया।

मेरी धारणा यह है कि इसे सभी रहस्यमय तरीके से करना है mongoose save लागू करता है। मैंने एनपीएम hooks का उपयोग करके इसके बारे में कुछ पढ़ा है, जो save विधि को फिसलने के लिए एक फिसलन चीज़ बनाता है।

मैंने mockgoose के बारे में भी सुना है, हालांकि मैंने अभी तक उस समाधान का प्रयास नहीं किया है। किसी को भी उस रणनीति के साथ सफलता मिली? [संपादित करें: मॉकगोस सेटअप/टियरडाउन की आसानी के लिए एक इन-मेमोरी डेटाबेस प्रदान करता है, लेकिन यह स्टबिंग के मुद्दे को हल नहीं करता है।]

इस समस्या को हल करने के तरीके पर कोई अंतर्दृष्टि बहुत सराहना की जाएगी।

उत्तर

2

यहाँ अंतिम विन्यास मैं विकसित की है, जो सिनोन और मजाक का एक संयोजन का उपयोग करता है:

// Dependencies 
var expect = require('chai').expect; 
var sinon = require('sinon'); 
var mockery = require('mockery'); 
var reloadStub = require('../../../spec/utils/reloadStub'); 

describe('UNIT: userController.js', function() { 

    var reportErrorStub; 
    var controller; 
    var userModel; 

    before(function() { 
    // mock the error reporter 
    mockery.enable({ 
     warnOnReplace: false, 
     warnOnUnregistered: false, 
     useCleanCache: true 
    }); 

    // load controller and model 
    controller = require('./userController'); 
    userModel = require('./userModel'); 
    }); 

    after(function() { 
    // disable mock after tests complete 
    mockery.disable(); 
    }); 

    describe('#createUser', function() { 
    var req; 
    var res; 
    var status; 
    var end; 
    var json; 

    // Stub `#save` for all these tests 
    before(function() { 
     sinon.stub(userModel.prototype, 'save'); 
    }); 

    // Stub out req and res 
    beforeEach(function() { 
     req = { 
     body: { 
      username: 'Andrew', 
      userID: 1 
     } 
     }; 

     status = sinon.stub(); 
     end = sinon.stub(); 
     json = sinon.stub(); 

     res = { status: status.returns({ end: end, json: json }) }; 
    }); 

    // Reset call count after each test 
    afterEach(function() { 
     userModel.prototype.save.reset(); 
    }); 

    // Restore after all tests finish 
    after(function() { 
     userModel.prototype.save.restore(); 
    }); 

    it('should call `User.save`', function(done) { 
     controller.createUser(req, res); 
     /** 
     * Since Mongoose's `new` is asynchronous, run our expectations on the 
     * next cycle of the event loop. 
     */ 
     setTimeout(function() { 
     expect(userModel.prototype.save.callCount).to.equal(1); 
     done(); 
     }, 0); 
    }); 
    } 
} 
+0

यह मेरे लिए काम किया! साझा करने के लिए बहुत बहुत धन्यवाद! <3 –

1

आप की कोशिश की है:

sinon.stub(userModel.prototype, 'save') 

इसके अलावा, जहां सहायक कार्य परीक्षण के लिए बुलाया जा रहा है? ऐसा लगता है कि आप फ़ंक्शन को utils मॉड्यूल के रूप में परिभाषित करते हैं, लेकिन इसे नियंत्रक ऑब्जेक्ट की विधि के रूप में कॉल करें। मुझे लगता है कि इस त्रुटि संदेश से इसका कोई लेना-देना नहीं है, लेकिन इससे यह पता लगाना मुश्किल हो गया कि स्टब कब और कहां बुलाया जा रहा था।

+0

प्रतिक्रिया के लिए धन्यवाद। पकड़ के लिए धन्यवाद। मॉड्यूल के रूप में फ़ंक्शन को परिभाषित करने में अंतर और बाद में इसे विधि के रूप में बुलाया गया था, कोड को साफ करते समय और SO के लिए इसे सरल बनाते समय एक त्रुटि उत्पन्न हुई थी। मैंने इसे अभी सही कर दिया है। – AndrewSouthpaw

+0

मैंने 'sinon.stub (userModel.prototype, 'save') का उपयोग करने का प्रयास किया था। यह 'सेव' विधि पर व्यवहार को सटीक रूप से कैप्चर करता है, लेकिन यह अभी भी पहले वर्णित 'TypeError' फेंकता है। – AndrewSouthpaw