2013-09-22 104 views
15

Tôi đang nghiên cứu phát triển API REST bằng ExpressJS, NodeJS, Mongoose và Mocha.Đảm bảo ứng dụng Express đang chạy trước mỗi Kiểm tra Mocha

Điều này là tôi có tệp app.coffee, đó là trách nhiệm thiết lập ExpressJS và kết nối với Mongoose. Cách tôi đã thiết lập này là Mongoose được kết nối đầu tiên và nếu điều đó được thông qua, sau đó, các ứng dụng ExpressJS được bắt đầu.

Vấn đề là khi thiết lập Mocha, tôi cần đảm bảo rằng ứng dụng ExpressJS hiện có trong app.coffee được bắt đầu thành công bao gồm tất cả mã không đồng bộ trước khi bất kỳ testcase nào được thực hiện.

Đối với điều đó, tôi đã tạo một test_helper.coffee và đặt mã sau vào nó, nhưng, testcases bắt đầu thực thi ngay cả khi mã trong app.coffee chưa hoàn thành việc thực thi hoàn toàn có ý nghĩa:

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

Tóm lại, tôi muốn đảm bảo rằng ứng dụng ExpressJS đã hoàn thành hoàn tất thiết lập trước khi bất kỳ testcase nào được thực hiện.

Tôi có thể làm như thế nào?

+0

Tôi đã gặp phải sự cố tương tự. Tôi đã thiết kế lại máy chủ tốc hành của mình và bây giờ nó không đợi kết nối cơ sở dữ liệu hoặc bất kỳ loại khởi tạo không đồng bộ nào. Đó cũng là lý tưởng cho các máy chủ REST vì nó không cần thiết để kết nối với cơ sở dữ liệu ngay cả khi không có yêu cầu đến một môi trường REST. Ngoài ra, mỗi cuộc gọi không nhất thiết cần tất cả các mô hình. Trong trường hợp của tôi, tôi khởi tạo cơ sở dữ liệu khi cần thiết mà hầu như mọi cuộc gọi đều thực hiện. – Kamrul

+0

@Kamrul: Bạn có thể vui lòng chia sẻ một số mã mẫu như cách bạn đã làm điều đó không? –

Trả lời

1

Bạn không cần nghe cổng để thử nghiệm ứng dụng của mình. Bạn có thể sử dụng thư viện thử nghiệm supertest với ứng dụng của mình và nó sẽ ổn.

Có thể bạn sẽ cần phải kết nối với cơ sở dữ liệu hoặc ứng dụng khách redis. Bạn có thể làm điều này trong phương thức configure của ứng dụng của bạn. Vì nút lưu trữ các mô-đun, bạn có thể yêu cầu mô-đun ứng dụng trong các mô-đun thử khác nhau mà không cần kết nối lại.

+0

Vấn đề là thiết lập ứng dụng của tôi không đồng bộ, kể cả khi tuyến đường tốc hành của tôi sẵn sàng, vì vậy, siêu cầu sẽ không thành công mỗi khi cố gắng nhấn tuyến đường đó vì tuyến đường đó bắt đầu quá sớm. – writofmandamus

+0

Bạn cần nghe cổng. Bạn chỉ có thể cho phép supertest [làm điều đó cho bạn] (https://github.com/visionmedia/supertest/blob/199506d8dbfe0bb1434fc07c38cdcd1ab4c7c926/lib/test.js#L59). – dvlsg

1

Có thể có cách đơn giản hơn, nhưng tôi đã đến Grunt để tự động hóa các bài kiểm tra chức năng của mình. Có một plugin nhanh và mocha để đạt được mục tiêu của bạn. My 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']) 
} 

tiền thưởng: thêm 'grunt' làm móc trước git. Bằng cách này, bạn không thể cam kết mà không vượt qua tất cả các bài kiểm tra

15

Tôi đến muộn, nhưng tôi đã tìm ra cách tốt nhất để thiết lập bộ thử nghiệm mocha cho ứng dụng nhanh là tạo tệp app.js hoặc server.js của tôi xuất khẩu các đối tượng ứng dụng, như thế này:

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; 

chắc chắn rằng tập tin cấu hình của bạn có môi trường khác nhau như phát triển, thử nghiệm, sản xuất thiết lập:

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: { 
    // ... 
    } 
} 

sau đó trong các tập tin thử nghiệm của bạn, bạn có thể đi trước và yêu cầu ứng dụng của bạn, sẽ kết nối với db bên phải và trên cổng bên phải:

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(); 
     }); 
     }); 
    }); 

Và cuối cùng, để bắt đầu lên toàn bộ quái vật bạn bao gồm này trong thư mục package.json (hãy chắc chắn để có nodemon và mocha trong devDependencies của bạn):

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

Bây giờ bạn có thể bắt đầu bộ kiểm tra của bạn với npm test và ứng dụng của bạn với npm start.

Hy vọng điều đó sẽ hữu ích! ps: hầu hết những thứ tôi đã học được khi xem ví dụ tuyệt vời này: https://github.com/madhums/node-express-mongoose-demo

+5

Supertest biết khi ứng dụng expressjs đã sẵn sàng để sử dụng? Làm thế nào để bạn đảm bảo rằng cơ sở dữ liệu sẵn sàng sử dụng khi các động từ http của bạn được khởi tạo? – raffomania

+0

vì tôi xuất ứng dụng từ tệp app.js của mình và yêu cầu nó ở đầu mỗi tệp kiểm tra – tmaximini

+3

Nhưng còn db thì sao? AFAIK bạn phải sử dụng một cái gì đó như 'mongoose.connection.once ('mở', gọi lại)' và sau đó thêm các tuyến đường của bạn. Điều này có nghĩa là ứng dụng thực sự được khởi tạo không đồng bộ. Làm thế nào để bạn xử lý đó? – raffomania

2

Tôi gặp vấn đề tương tự khi sử dụng hoa nhài/supertest để kiểm tra ứng dụng nhanh của mình. Tôi giải quyết vấn đề bằng cách phát ra khi ứng dụng đã sẵn sàng và chỉ chạy thử nghiệm của tôi sau đó. Dưới đây là cấu trúc thư mục của tôi

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

Trong server.js khi từng máy chủ của bạn được thiết lập và bạn đã sẵn sàng để chạy thử nghiệm của bạn thêm app.emit('started');. Và đảm bảo xuất ứng dụng của bạn! Trong setup.spec.js bạn có thể xem sự kiện được phát ra.

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); 
    }); 
}); 

Ý tưởng cùng sho uld làm việc cho mocha. Here is an article explaining this for mocha. Bạn chỉ cần thay đổi beforeAll thành before.

+0

cảm ơn, đây là bởi đến nay giải pháp tốt nhất cho tôi – DanP

+0

Yep này làm việc cho tôi quá, chỉ cần thêm phát ra sau khi bạn initilise/bắt đầu máy chủ sau đó kiểm tra app.on nó trong chức năng trước - câu trả lời tốt nhất cho đến nay – AKMorris

0

Phương thức app.listen thực hiện gọi lại khi mọi thứ đã sẵn sàng. Vì vậy, bạn cần để có thể vượt qua gọi lại thực hiện ở đó. Một cái gì đó như

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