2016-09-18 40 views
-2

我對測試很陌生,對Sinon存根和嘲having有困難。 如何爲後續的senario編寫'quote.list_quote'測試。如何使用Mocha,Chai和Sinon測試node.js-mongodb應用程序?我對Sinon部分有困難

這裏是路線文件:quotes.js

const express = require('express'); 
const request = require('request'); 
const async = require('async'); 
const validator = require('validator'); 

const quote_router = express.Router(); 

const confg = require("../../confg/confg"); 
const quote = require("../models/mquotes"); 
const quotes_model = quote.quotes; 

// host name - needs to be set up using the environment variable 
const hostname = confg.hostname; 

// route for "quotes/" 
quote_router.route("/") 
// get route : display the random quote 
.get((req, res) => { 
    // display random quote 
    async.waterfall([ 
      (callback) => {callback(null, {res});}, 
      quote.count_quotes 
     ], check_quote_exist 
    ); 
}) 
// post route : create a new quote 
.post((req, res) => { 
    const doc_json = {author : validator.escape(req.body.quote_author), quote_text : validator.escape(req.body.quote_text)}; 
    const params = {res, doc_json, quote_action : quote.create_quote}; 
    add_edit_quote(params); 
}) 
// put route : edit the quote 
.put((req, res) => { 
    const doc_json = {author : validator.escape(req.body.quote_author), quote_text : validator.escape(req.body.quote_text)}; 
    const params = {res, doc_json, quote_action : quote.update_quote, qid : req.body.quote_id}; 
    add_edit_quote(params); 
}) 
// delete quote : delete the quote 
.delete((req, res) => { 
    const qid = req.body.qid; 
    const condition = {_id : qid}; 
    async.waterfall([ 
      (callback) => {callback(null, {res, condition});}, 
      quote.delete_quote 
     ], request_quote_list 
    ); 
}); 

// route for "quotes/list" : display quotes list 
quote_router.get("/list/", (req, res) => { 
    // mention the main operation 
    let operation; 

    if(req.body.operation != 'undefined') { 
     operation = req.body.operation; 
    } else { 
     operation = "list_quotes"; 
    } 

    async.waterfall([ 
      (callback) => {callback(null, {res, operation});}, 
      quote.list_quote 
     ], display_quotes_list 
    ); 
}); 
// display the quotes list 
const display_quotes_list = (err, params, quotes_list) => { 
    if (err) {return console.log(err);} 

    const res = params.res; 
    const operation = params.operation; 
    const header_msg = "List of all the quotes"; 
    let alert_msg; 

    if(operation == "list_quotes") { 
     alert_msg = null; 
    } else if(operation == "delete_quote") { 
     alert_msg = "Quote has been deleted"; 
    } 

    const params_out = { 
     page: "quote_list", 
     title: 'Quotes Manager', 
     host: hostname, 
     header_msg, 
     alert_msg, 
     quotes_list 
    }; 
    res.render('index', params_out); 
}; 

// send http request for quote list page 
const request_quote_list = (err, params) => { 
    if (err) {return console.log(err);} 

    const res = params.res; 
    const operation = "delete_quote"; 

    request.get('http://' + hostname + '/quotes/list/', {json:{operation}}, 
     (error, response, body) => { 
      if (!error && response.statusCode == 200) { 
       res.send(body); 
      } 
    }); 
}; 

module.exports = quote_router; 

這是不完整的文件。我只包括它的一部分。

而且她是模型文件:mquotes.js

const mongoose = require('mongoose'); 

// Define quote schema 
const quoteSchema = new mongoose.Schema({ 
    author: String, 
    quote_text: {type: String, required: true} 
    }, 
    {timestamps: true} 
); 
const quote = {}; 

// Define quotes model 
quote.quotes = mongoose.model('quotes', quoteSchema); 

// error handler 
error_handler = (callback, err, params, return_value) => { 
    if(err) { return callback(err);} 
    else {callback(null, params, return_value);} 
}; 

// add quote - create 
quote.create_quote = (params, callback) => { 
    const res = params.res; 
    const doc_json = params.doc_json; 
    quote.quotes.create(doc_json, (err, quotes_detail) => { 
     error_handler(callback, err, {res, operation : 'create_quote'}, quotes_detail); 
    }); 
}; 

// count the number of quotes 
quote.count_quotes = (params, callback) => { 
    quote.quotes.count({}, (err, quotes_count) => { 
     error_handler(callback, err, params, quotes_count); 
    }); 
}; 

// delete quote - delete - id 
quote.delete_quote = (params, callback) => { 
    quote.quotes.remove(params.condition, (err, query) => { 
     error_handler(callback, err, params); 
    }); 
}; 

// list quote - find 
quote.list_quote = (params, callback) => { 
    quote.quotes.find({}, (err, quotes_list) => { 
     error_handler(callback, err, params, quotes_list); 
    }); 
}; 

// find quote by id 
quote.quote_by_id = (params, callback) => { 
    quote.quotes.findById(params.qid, (err, quotes_detail) => { 
     error_handler(callback, err, params, quotes_detail); 
    }); 
}; 

// returns the detail of random quote 
quote.random_qoute = (params, callback) => { 
    const random_number = params.random_number; 

    // select one quote after skipping random_number of times 
    quote.quotes.findOne({}, (err, quotes_detail) => { 
     error_handler(callback, err, params, quotes_detail); 
    }).skip(random_number); 
}; 

// update quote - update - id 
quote.update_quote = (params, callback) => { 
    const options = {new: true}; 
    const qid = params.qid; 
    const update_json = params.doc_json; 

    quote.quotes.findByIdAndUpdate(qid, {$set: update_json}, options, (err, quotes_detail) => { 
     params.operation = 'update_quote'; 
     error_handler(callback, err, params, quotes_detail); 
    }); 
}; 

module.exports = quote; 

我已經安裝了全球摩卡。現在,我想測試模型。例如,讓我們以quote.list_quote函數爲例。

const mongoose = require('mongoose'); 
const chai = require('chai'); 
const sinon = require('sinon'); 

const expect = chai.expect; // use the "expect" style of Chai 
const mquotes = require('./../../app/models/mquotes'); 

describe('Tests for quote models',() => { 
    describe("List quote",() => { 
     it('list_quote() should return list of quotes',() => { 

     }); 
    }); 
}); 

誰能告訴我關於我的編碼實踐嗎?我的意思是我使用功能和模塊的方式。

回答

1

首先,您應該嘗試使用statics方法。在此之後,如果您想在貓鼬中使用Promise,則應使用sinon-mongoosesinon-as-promised

這是我的示例代碼和測試與摩卡,柴,和sinon。希望對你有用。

model.js

var Schema = new mongoose.Schema({ 
    name: String, 
    created_at: { 
     type: Date, 
     default: Date.now 
    }, 
    updated_at: { 
     type: Date, 
     default: Date.now 
    } 
}); 

Schema.statics.findByName = function(name, cb) { 
    this.findOne({ 
      name: name 
     }) 
     .exec() 
     .then(function getTemplate(template) { 
      if (!template) { 
       var error = new Error('Not found template by name: "' + name + '"'); 
       error.status = 404; 
       return cb(error); 
      } 

      return cb(null, template); 
     }) 
     .catch(function catchErrorWhenFindByTemplateName(error) { 
      error.status = 500; 
      return cb(error); 
     }); 
} 

module.exports = mongoose.model('model', Schema); 

test.js

var expect = require('chai').expect, 
    sinon = require('sinon'), 
    mongoose = require('mongoose'); 

require('sinon-as-promised'); 
require('sinon-mongoose'); 

var Model = require('../../app/models/model'); 

describe('Model', function() { 

    describe('static methods', function() { 

    describe('#findByName', function() { 

     var ModelMock; 

     beforeEach(function() { 
     ModelMock = sinon.mock(Model); 
     }); 

     afterEach(function() { 
     ModelMock.restore(); 
     }); 

     it('should get error status 404 if not found template', function (done) { 
     var name = 'temp'; 
     ModelMock 
      .expects('findOne').withArgs({name: name}) 
      .chain('exec') 
      .resolves(null); 

     Model.findByName(name, function (error) { 
      expect(error.status).to.eql(404); 
      ModelMock.verify(); 
      done(); 
     }); 

     }); 

     it('should get message not found template if name is not existed', function (done) { 
     var name = 'temp'; 
     ModelMock 
      .expects('findOne').withArgs({name: name}) 
      .chain('exec') 
      .resolves(null); 

     Model.findByName(name, function (error) { 
      expect(error.message).to.match(/Not found template by name/gi); 
      ModelMock.verify(); 
      done(); 
     }); 

     }); 

     it('should get template when name is existed', function (done) { 
     var name = 'temp'; 
     ModelMock 
      .expects('findOne').withArgs({name: name}) 
      .chain('exec') 
      .resolves('SUCCESS'); 

     Model.findByName(name, function (error) { 
      expect(error).to.be.null; 
      ModelMock.verify(); 
      done(); 
     }); 
     }); 

     it('should get error status 500 when model crashed', function (done) { 
     var name = 'temp'; 
     ModelMock 
      .expects('findOne').withArgs({name: name}) 
      .chain('exec') 
      .rejects(new Error('Oops! Crashed')); 

     Model.findByName(name, function (error) { 
      expect(error.status).to.eql(500); 
      ModelMock.verify(); 
      done(); 
     }); 

     }); 

    }); 

    }); 

}); 
+0

非常感謝把精力用於解決方案。我真的很難與sinon。這將是一個很大的幫助。 – iiR

相關問題