繁体   English   中英

从大型MongoDB集合动态生成Mocha测试

[英]Dynamically generating Mocha tests from a large MongoDB collection

在我的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的结果流

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接收数据”测试取得进展,但是当它开始执行“符合模式的一致性”测试时,它将引发与上述相同的内存不足错误。

关于我可以尝试的其他想法?

嗯,这并没有解决原来的问题,但我不得不满足于使用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()
      })
    })
 })
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM