在我的Node.js项目测试套件中,我想对照JSON模式检查MongoDB集合中的每个项目。使用Mocha测试框架,我可以像这样动态地生成测试:
describe('Lexemes', () => {
// load schema validator
var schema = JSON.parse(fs.readFileSync('public/schemas/lexeme.json'))
var validate = ajv.compile(schema)
it('receives data', async () => {
// load all items in collection
let items = await db.get('lexemes').find()
items.forEach((item) => {
// dynamically generated test for each result
describe(item._id, () => {
it('conforms to schema', () => {
validate(item).should.be.true()
})
})
})
})
})
这非常适合较小的收藏。但是,有了一个非常大的馆藏(450万个文档),我就会超时:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
如果仅将超时时间增加到60秒,最终会出现 JavaScript堆内存不足错误。显然,它正在尝试将整个集合存储在内存中,这将无法正常工作。
我认为我可以像这样使用Monk's result streaming:
it('receives data', () => {
return db.get('lexemes').find().each((item, { close, pause, resume }) => {
describe(item._id, () => {
it('conforms to schema', () => {
validate(item).should.be.true()
})
})
})
})
但是,这没有什么区别(请注意,我也尝试过返回一个Promise而不是使用async / await,这也没有帮助)。
编辑1
我尝试使用Mongo查询的limit / skip选项手动将数据分页为较小的块:
const limit = 1000 // page size
var skip = 0
do {
it(`receives data ${skip} to ${skip + limit - 1}`, async () => {
let items = await db.get('lexemes').find({}, { limit: limit, skip: skip })
items.forEach((item) => {
describe(item._id, () => {
it('conforms to schema', () => {
validate(item).should.be.true()
})
})
})
})
skip += limit
} while (skip < 5000000)
编辑2
这避免了超时错误,并且Mocha在“从x接收数据到y的数据”测试中似乎正在取得进展,但是当它开始执行“符合模式的一致性”测试时,它将引发与上述相同的内存不足错误。
关于我可以尝试的其他想法吗?
答案 0 :(得分:0)
这并不能解决最初的问题,但是我不得不使用MongoDB的$sample
聚合功能来测试来自大型集合的数据的样本:>
const limit = 100000 // sample size
it(`receives data (${limit} samples)`, async () => {
let items = await db.get('lexemes').aggregate([{ '$sample': { 'size': limit } }])
items.forEach((item) => {
describe(item._id}, () => {
it('conforms to schema', () => {
validate(item).should.be.true()
})
})
})
})