Mocha 抛出超时,但 Mongoose 将数据保存到 Promise 链中的数据库?
Mocha throws timeout exceeded, yet Mongoose saves data to DB in Promise chain?
我正在使用 Mocha、Mongoose 和 MongoDB。
我的目标只是 运行 围绕创建帐户进行测试。我有以下代码:
require( "./../../config/config" );
var mongoose = require( "mongoose" );
mongoose.connect( process.env.MONGODB_URI );
const expect = require( "expect" );
var { Account } = require( "./../../models/account" );
describe( "Account Creation", () =>
{
it( "should successfully create an account", ( done ) =>
{
var data =
{
username: "PrestonJ",
email: "someEmail@mail.com",
password: "somePassword123!"
};
var account = new Account( data );
account.save().then( ( result ) =>
{
console.log( "(temporary log) account saved" );
done();
}).catch( ( e ) => done( e ) );
});
});
Mongoose 承诺链执行并将新帐户保存到数据库中,但从未达到 done()
(即使已写入,并且上面的控制台调用有效)。
这导致摩卡测试失败,给我:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
我曾尝试 return
Promise 链,但这也不起作用。我也曾尝试完全删除 done
并返回链条,但无济于事。
几个小时过去了,我一直找不到合适的 practices/fixes。
编辑:
我试过增加摩卡咖啡的超时时间。错误是否以某种方式被吞没了?它在我的模型文件中吗?
编辑 2:
这是帐户模型的来源:
var mongoose = require( "mongoose" );
const _ = require( "lodash" );
const validator = require( "validator" );
const jwt = require( "jsonwebtoken" );
const bcrypt = require( "bcryptjs" );
let Account_CollectionName = "accounts";
var Account_Schema = new mongoose.Schema(
{
username:
{
type: String,
minLength: 3,
trim: true,
required: true,
unique: true
},
email:
{
type: String,
minlength: 1,
trim: true,
required: false,
unique: true,
sparse: true,
validate: validator.isEmail,
message: "{VALUE} is not a valid email"
},
password:
{
type: String,
required: true,
minLength: 5
},
tokens:
[{
access:
{
type: String,
required: true
},
token:
{
type: String,
required: true
}
}],
},
{
collection: Account_CollectionName
});
Account_Schema.pre( "save", function( next )
{
var account = this;
if( account.isModified( "password" ) )
{
bcrypt.genSalt( 10, ( err, salt ) =>
{
bcrypt.hash( account.password, salt, ( err, hash ) =>
{
account.password = hash;
next();
});
});
}
else
next();
});
Account_Schema.methods.toJSON = function()
{
var account = this;
var accountObject = account.toObject();
return _.pick( accountObject,
[
"_id", "username", "email"
] );
};
Account_Schema.methods.generateAuthToken = function()
{
var account = this;
var access = "auth";
var token = jwt.sign( { _id: account._id.toHexString(), access }, process.env.JWT_SECRET ).toString();
account.tokens = account.tokens.concat( [{ access, token }] );
return account.save().then( () =>
{
return token;
});
};
Account_Schema.statics.findByToken = function( token )
{
var Account = this;
var decoded;
try {
decoded = jwt.verify( token, process.env.JWT_SECRET );
}
catch( e )
{
return Promise.reject();
}
return Account.findOne(
{
"_id" : decoded._id,
"tokens.token": token,
"tokens.access": "auth"
});
};
Account_Schema.statics.findByCredentials = function( username, password )
{
var Account = this;
return Account.findOne( { username } ).then( ( account ) =>
{
if( ! account )
return Promise.reject();
return new Promise( ( resolve, reject ) =>
{
bcrypt.compare( password, account.password, ( err, res ) =>
{
if( res )
resolve( account );
else
reject();
});
});
});
};
Account_Schema.methods.removeToken = function( token )
{
var account = this;
return account.update(
{
$pull:
{
tokens: { token }
}
});
};
var Account = mongoose.model( Account_CollectionName, Account_Schema );
module.exports = { Account };
您收到此错误是因为 mocha 在完成保存操作之前等待了 200 毫秒的时间段,并且由于此操作花费了超过 200 毫秒,您的测试失败了。
处理此类问题的最佳方法是了解您的应用响应所需的最长时间并将该时间设置为超时。
您只需添加一个标志就可以为 mocha 测试设置超时 timeout
您可以在 mocha.opts 文件中将其提供为
--timeout 50000
这将使您的测试用例在任何操作超时之前等待 50 秒。
我明白了。许多事情需要完成;这是 it
块的固定来源:
it( "should successfully create an account", () =>
{
var data =
{
username: "PrestonJ",
email: "someEmail@mail.com",
password: "somePassword123!"
};
let account = new Account( data );
return account.save().then( ( result ) =>
{
if( result )
{
console.log( "Successful!" );
return Promise.resolve();
}
else
return Promise.reject( "cannot save" );
}).catch( ( e ) =>
{
return Promise.reject( e );
});
});
- 删除
done
/done()
的所有痕迹
return
account.save().then(...)...
- 在
then()
中,使用return Promise.resolve()
代替done()
- 在
catch()
中,使用return Promise.reject(e)
代替done(e)
我正在使用 Mocha、Mongoose 和 MongoDB。
我的目标只是 运行 围绕创建帐户进行测试。我有以下代码:
require( "./../../config/config" );
var mongoose = require( "mongoose" );
mongoose.connect( process.env.MONGODB_URI );
const expect = require( "expect" );
var { Account } = require( "./../../models/account" );
describe( "Account Creation", () =>
{
it( "should successfully create an account", ( done ) =>
{
var data =
{
username: "PrestonJ",
email: "someEmail@mail.com",
password: "somePassword123!"
};
var account = new Account( data );
account.save().then( ( result ) =>
{
console.log( "(temporary log) account saved" );
done();
}).catch( ( e ) => done( e ) );
});
});
Mongoose 承诺链执行并将新帐户保存到数据库中,但从未达到 done()
(即使已写入,并且上面的控制台调用有效)。
这导致摩卡测试失败,给我:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
我曾尝试 return
Promise 链,但这也不起作用。我也曾尝试完全删除 done
并返回链条,但无济于事。
几个小时过去了,我一直找不到合适的 practices/fixes。
编辑: 我试过增加摩卡咖啡的超时时间。错误是否以某种方式被吞没了?它在我的模型文件中吗?
编辑 2: 这是帐户模型的来源:
var mongoose = require( "mongoose" );
const _ = require( "lodash" );
const validator = require( "validator" );
const jwt = require( "jsonwebtoken" );
const bcrypt = require( "bcryptjs" );
let Account_CollectionName = "accounts";
var Account_Schema = new mongoose.Schema(
{
username:
{
type: String,
minLength: 3,
trim: true,
required: true,
unique: true
},
email:
{
type: String,
minlength: 1,
trim: true,
required: false,
unique: true,
sparse: true,
validate: validator.isEmail,
message: "{VALUE} is not a valid email"
},
password:
{
type: String,
required: true,
minLength: 5
},
tokens:
[{
access:
{
type: String,
required: true
},
token:
{
type: String,
required: true
}
}],
},
{
collection: Account_CollectionName
});
Account_Schema.pre( "save", function( next )
{
var account = this;
if( account.isModified( "password" ) )
{
bcrypt.genSalt( 10, ( err, salt ) =>
{
bcrypt.hash( account.password, salt, ( err, hash ) =>
{
account.password = hash;
next();
});
});
}
else
next();
});
Account_Schema.methods.toJSON = function()
{
var account = this;
var accountObject = account.toObject();
return _.pick( accountObject,
[
"_id", "username", "email"
] );
};
Account_Schema.methods.generateAuthToken = function()
{
var account = this;
var access = "auth";
var token = jwt.sign( { _id: account._id.toHexString(), access }, process.env.JWT_SECRET ).toString();
account.tokens = account.tokens.concat( [{ access, token }] );
return account.save().then( () =>
{
return token;
});
};
Account_Schema.statics.findByToken = function( token )
{
var Account = this;
var decoded;
try {
decoded = jwt.verify( token, process.env.JWT_SECRET );
}
catch( e )
{
return Promise.reject();
}
return Account.findOne(
{
"_id" : decoded._id,
"tokens.token": token,
"tokens.access": "auth"
});
};
Account_Schema.statics.findByCredentials = function( username, password )
{
var Account = this;
return Account.findOne( { username } ).then( ( account ) =>
{
if( ! account )
return Promise.reject();
return new Promise( ( resolve, reject ) =>
{
bcrypt.compare( password, account.password, ( err, res ) =>
{
if( res )
resolve( account );
else
reject();
});
});
});
};
Account_Schema.methods.removeToken = function( token )
{
var account = this;
return account.update(
{
$pull:
{
tokens: { token }
}
});
};
var Account = mongoose.model( Account_CollectionName, Account_Schema );
module.exports = { Account };
您收到此错误是因为 mocha 在完成保存操作之前等待了 200 毫秒的时间段,并且由于此操作花费了超过 200 毫秒,您的测试失败了。
处理此类问题的最佳方法是了解您的应用响应所需的最长时间并将该时间设置为超时。
您只需添加一个标志就可以为 mocha 测试设置超时 timeout
您可以在 mocha.opts 文件中将其提供为
--timeout 50000
这将使您的测试用例在任何操作超时之前等待 50 秒。
我明白了。许多事情需要完成;这是 it
块的固定来源:
it( "should successfully create an account", () =>
{
var data =
{
username: "PrestonJ",
email: "someEmail@mail.com",
password: "somePassword123!"
};
let account = new Account( data );
return account.save().then( ( result ) =>
{
if( result )
{
console.log( "Successful!" );
return Promise.resolve();
}
else
return Promise.reject( "cannot save" );
}).catch( ( e ) =>
{
return Promise.reject( e );
});
});
- 删除
done
/done()
的所有痕迹
return
account.save().then(...)...
- 在
then()
中,使用return Promise.resolve()
代替done()
- 在
catch()
中,使用return Promise.reject(e)
代替done(e)