Mocha 测试执行时间过长
Posted
技术标签:
【中文标题】Mocha 测试执行时间过长【英文标题】:Mocha tests taking too long to execute 【发布时间】:2015-05-07 14:01:29 【问题描述】:所以我正在开发一个 express.js 应用程序,其中我有一个猫鼬模型用户。我编写了一个测试文件(使用 Mocha)来测试 save() 函数,但是我所有的测试都需要很长时间才能执行并最终超时。
这是我得到的错误:
Testing - Server - User - Model
Testing save()
1) should be able to save without problems
2) should fail to save an exisitng user again
3) should should an error when try to save with empty email
4) should give an error when try to save with empty password
5) "after all" hook
0 passing (8s)
5 failing
1) Testing - Server - User - Model Testing save() should be able to save without problems:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
2) Testing - Server - User - Model Testing save() should fail to save an exisitng user again:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
3) Testing - Server - User - Model Testing save() should should an error when try to save with empty email:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
4) Testing - Server - User - Model Testing save() should give an error when try to save with empty password:
Uncaught AssertionError: expected null to exist
at Promise.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/test/models/user.server.model.test.js:69:12)
at Promise.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
at Promise.emit (events.js:98:17)
at Promise.emit (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
at Promise.fulfill (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
at handleSave (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/model.js:133:13)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/utils.js:408:16
at model.save (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/model.js:222:7)
at model._done (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:59:24)
at _next (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:52:28)
at fnWrapper (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:159:8)
at model.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/models/user.js:22:46)
at _next (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:50:30)
at fnWrapper (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:159:8)
at complete (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:992:5)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:983:20
at ObjectId.SchemaType.doValidate (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/schematype.js:603:22)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:974:9
at process._tickCallback (node.js:442:13)
5) Testing - Server - User - Model "after all" hook:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
这是我的测试文件:
// Module dependencies
var should = require("should");
var mongoose = require("mongoose");
var config = require('../../config/config');
var nodemailer = require('nodemailer');
var bcrypt = require('bcryptjs');
// Get User model
var User = require('../../models/user')(mongoose, config, bcrypt, nodemailer).User;
// Define global test variables
var user;
var user2;
// Unit tests
describe('Testing - Server - User - Model', function()
// Since its before - it happens once ONCE before ALL the tests
before(function(done)
// Since we're using the global variables don't use var in front of them
user = new User(
email: 'a@a.com',
password: 'a'
);
// Another user with same details as the first user cos
// For a test case, where we try to insert 2 records with same details (should fail as exprected)
user2 = new User(
email: 'a@a.com',
password: 'a'
);
done();
);
// Testing function #1 - save()
describe('Testing save()', function()
// Test case #1 - save normally
it('should be able to save without problems', function(done)
try
user.save(done);
catch (x)
done(x);
);
// Test case #2 - should fail to save an exisitng user again
it('should fail to save an exisitng user again', function(done)
user.save(function()
user2.save(function(err)
should.exist(err);
done();
);
);
)
// Test case #3 - should give an error when try to save with empty email
it('should should an error when try to save with empty email', function(done)
user.email = '';
return user.save(function(err)
should.exist(err);
done();
);
);
// Test case #4 - should give an error when try to save with empty password
it('should give an error when try to save with empty password', function(done)
return user.save(function(err)
should.exist(err);
done();
);
);
);
after(function(done)
User.remove().exec(done);
);
);
这是我的用户模型文件:
module.exports = function(mongoose, config, bcrypt, nodemailer)
// User schema
var userSchema = new mongoose.Schema(
email:
type: String,
unique: true,
lowercase: true
,
password:
type: String,
select: false
);
// Makes sure that our passwords are always hashed before saving to the database
// Refer to sessionBuddy's resources for more info on this
userSchema.pre('save', function(next)
var user = this;
// Only hash the password if its modified or new
if (!user.isModified('password')) return next();
// Generate salt
bcrypt.genSalt(config.SALT_WORK_FACTOR, function(err, salt)
if (err) return next(err);
// hash the password along with the salt
bcrypt.hash(user.password, salt, function(err, hash)
if (err) return next(err);
// overwrite the cleartext password with the hashed one
user.password = hash;
next();
);
);
);
// Password verification for cleartext and hashed passwords
userSchema.methods.comparePassword = function(password, done)
bcrypt.compare(password, this.password, function(err, isMatch)
done(err, isMatch);
);
;
var User = mongoose.model('User', userSchema);
return
User : User
我还尝试了 try/catch 方法来获取该线程的承诺:In mocha testing while calling asynchronous function how to avoid the timeout Error: timeout of 2000ms exceeded. 但这也不起作用。
感谢任何帮助! 谢谢
编辑:正如 cmets 中所建议的,我没有连接到测试文件中的数据库。 EDIT2:现在在最后 2 个测试中出现以下错误 - “未捕获的 AssertionError:预期 null 存在” EDIT3:实际上我的架构可以将“电子邮件”和“密码”保存为空,因为我没有将必填字段设置为真,在更新我的架构后,它可以工作。
【问题讨论】:
看起来您实际上并没有连接到 mongodb 数据库。如果你不这样做,你的所有请求都将被排队并且永远不会被执行。 另外,如果您想在没有设置数据库的情况下仍然拥有测试环境,您可以使用rewire
重新定义 User#save
是的,很抱歉我实际上并没有连接到数据库。谢谢大家的帮助
我现在实际上遇到了另一个问题。对于最后 2 次测试,我收到以下消息:“Uncaught AssertionError: expected null to exist”知道这意味着什么吗?
【参考方案1】:
正如 cmets 中所指出的,您实际上并没有连接到 mongodb 数据库。您的所有请求都将由 Mongoose 排队,并且在您连接到数据库之前永远不会执行(从而在您的测试中产生超时)。
编辑 至于你的第二个问题,当它实际上没有产生任何错误时,你期望错误存在。此行未通过您的测试:
should.exist(err);
您应该检查您的模型。在您的第三个测试用例中,您要求用户拥有电子邮件,但您的模型并没有强制要求。密码也是一样。 此外,您不会在测试中将密码设为空。
【讨论】:
是的,你是对的。我刚刚对它进行了编辑。感谢您的帮助以上是关于Mocha 测试执行时间过长的主要内容,如果未能解决你的问题,请参考以下文章
在 mocha 中,如何在执行另一个测试之前等待异步测试结束?