2013-09-22 53 views
15

我正在使用ExpressJS,NodeJS,Mongoose和Mocha開發REST API。確保快速應用程序在每個摩卡測試之前運行

問題是我有一個app.coffee文件,它負責設置ExpressJS並連接到Mongoose。我設置的方式是,首先連接Mongoose,如果通過,則啓動ExpressJS應用程序。

問題是,在設置Mocha時,我需要確保app.coffee中存在的ExpressJS App在執行任何測試用例之前已成功完成,包括所有異步代碼。

爲此,我創建了一個test_helper.coffee並在其中放置了以下代碼,但即使app.coffee中的代碼尚未完全執行,實際上有意義,測試用例也會開始執行:

before (done) -> 
    require(__dirname + '/../src/app') 
    done() 

簡而言之,我想確保ExpressJS應用程序在執行任何測試用例之前已完全完成其設置。

我該怎麼做?

+0

我遇到了完全類似的問題。我重新設計了我的快速服務器,現在不要等待數據庫連接或任何類型的異步初始化。這對於REST服務器來說也很理想,因爲即使沒有請求進入REST環境,也不需要連接到數據庫。此外,每次通話並不一定需要所有型號。 在我的情況下,我幾乎每次調用都需要初始化數據庫。 – Kamrul

+0

@Kamrul:你可以請你分享一些示例代碼,如何做到這一點? –

回答

1

你不需要聽一個端口來測試你的應用程序。您可以使用supertest測試庫與您的應用程序,它應該沒問題。

儘管您可能需要連接到數據庫或redis客戶端。您可以在您的應用的configure方法中執行此操作。由於節點緩存模塊,因此您可以在不同的測試模塊中要求應用模塊,而無需重新連接。

+0

問題是我的應用程序安裝程序是異步的,包括當我的快速路線準備好時,所以超級跑車每次嘗試擊中該路線都會失敗,因爲它啓動得太快。 – writofmandamus

+0

你確實需要聽一個端口。你可以讓supertest [爲你做](https://github.com/visionmedia/supertest/blob/199​​506d8dbfe0bb1434fc07c38cdcd1ab4c7c926/lib/test.js#L59)。 – dvlsg

1

可能有一個更直接的方法,但我去Grunt自動化我的功能測試。有一個快速和摩卡插件來達到你的目標。我的gruntfile:

'use strict'; 

module.exports = function (grunt) { 
grunt.initConfig({ 
    express: { 
     options: {} 
     , test: { 
      options: { 
       script: './app.js' 
      } 
     } 
    } 
    , simplemocha: { 
     options: { 
      globals: ['should'] 
      , timeout: 8000 
      , ignoreLeaks: false 
      , ui: 'bdd' 
      , reporter: 'tap' 
     } 
     , all: { src: ['tests/*.test.js'] } 
    } 
}) 

grunt.loadNpmTasks('grunt-express-server') 
grunt.loadNpmTasks('grunt-simple-mocha') 

grunt.registerTask('default', ['express:test', 'simplemocha', 'express:test:stop']) 
} 

獎勵:將'grunt'添加爲git pre-commit hook。這種方式,你不能沒有通過所有的測試

15

我遲到了派對,但我發現設置我的摩卡測試套件的快速應用程序的最佳方式是使我的app.js或server.js文件導出應用程序對象,像這樣:

var mongoose = require('mongoose'); 
var express = require('express'); 
require('express-mongoose'); 

var env = process.env.NODE_ENV || 'development'; 
var config = require('./config/config')[env]; 

var models = require('./app/models'); 
var middleware = require('./app/middleware'); 
var routes = require('./app/routes'); 

var app = express(); 

app.set('port', process.env.PORT || config.port || 3000); 
app.set('views', __dirname + '/app/views'); 
app.set('view engine', 'jade'); 

// database 
mongoose.connect(config.db); 

// middleware 
middleware(app); 

// Application routes 
routes(app); 

app.listen(app.get('port')); 
console.log('Express server listening on port ' + app.get('port')); 

// export app so we can test it 
exports = module.exports = app; 

確保您的配置文件都有不同的環境,如開發,測試,生產設置:

var path = require('path'); 
var rootPath = path.normalize(__dirname + '/..'); 

module.exports = { 
    development: { 
    db: 'mongodb://localhost/my_dev_db', 
    port: 3000 
    }, 
    test: { 
    db: 'mongodb://localhost/my_test_db', 
    port: 8888 
    }, 
    production: { 
    // ... 
    } 
} 

然後在您的測試文件,你可以繼續要求你的應用程序,它將連接到正確的數據庫和正確的端口:

var should = require('chai').should(); 
var request = require('supertest'); 
var mongoose = require('mongoose'); 

var app = require('../app'); 
var agent = request.agent(app); 

var User = mongoose.model('User'); 

    // get users 
    describe('GET /api/users', function() { 
     it('returns users as JSON', function(done) { 
     agent 
     .get('/api/users') 
     .expect(200) 
     .expect('Content-Type', /json/) 
     .end(function(err, res) { 
      if (err) return done(err); 
      res.body.should.have.property('users').and.be.instanceof(Array); 
      done(); 
     }); 
     }); 
    }); 

最後,啓動了整個怪獸包括這在你的package.json(請務必在你的devDependencies nodemon和摩卡):

"scripts": { 
    "start": "NODE_ENV=development ./node_modules/.bin/nodemon app.js", 
    "test": "NODE_ENV=test ./node_modules/.bin/mocha --reporter spec test/**.js" 
    } 

現在你可以開始你的測試套件npm test和您的應用程序npm start

希望它有幫助! PS:大部分的東西我從看着這個驚人的例子瞭解到: https://github.com/madhums/node-express-mongoose-demo

+5

supertest是否知道expressjs應用程序何時可以使用?當你的http動詞初始化時,你如何保證數據庫準備好使用? – raffomania

+0

,因爲我從我的app.js文件中導出應用程序並要求它位於每個測試文件的頂部 – tmaximini

+3

但是db怎麼辦? AFAIK你必須使用'mongoose.connection.once('open',callback)''然後添加你的路由。這意味着應用程序是異步初始化的。你如何處理? – raffomania

2

我碰到了同樣的問題,而使用茉莉/ supertest測試我的快遞應用程序。我通過在應用程序準備就緒時發出並僅在之後運行測試來解決問題。這裏是我的目錄結構

- server.js 
- spec 
    - setup.spec.js 
    - test.spec.js 

server.js當過你的服務器設置,你準備好運行測試添加app.emit('started');。並確保導出您的應用程序!在setup.spec.js中,您可以觀看要發射的事件。

server.js

const express = require('express'); 
const app = express(); 
module.exports = app; // for testing 

setTimeout(() => { 
    app.listen(process.env.PORT || 3000); 
}); 

setup.spec.js

test.spec.js

const request = require('supertest'); 
const server = require('../index'); 

describe('test',() => { 
    it('test server works', done => { 
     request(server).get('/test').expect(200); 
    }); 
}); 

同樣的想法笑也爲摩卡工作。 Here is an article explaining this for mocha。您應該將beforeAll更改爲before

+0

的出口應用程序謝謝,這是迄今爲止對我來說最好的解決方案 – DanP

+0

是的這也適用於我,只需添加發射後,你啓動/啓動服務器,然後檢查app.on它在前功能 - 最好的答案 – AKMorris

0

app.listen方法需要一個回調,當一切準備就緒時運行。所以,你需要能夠將完成的回調傳遞給那裏。類似於

before (done) -> 
    var app = require(__dirname + '/../src/app') 
    app.listen(3000, done) 
相關問題