JEST和MongoDB的异步问题

时间:2018-10-23 18:42:13

标签: mongodb express mongoose jestjs

当我尝试使用beforeEach()挂钩从MongoDB集合中删除项目时,JEST的结果不一致。

我的Mongoose模式和模型定义为:

// Define Mongoose wafer sort schema
const waferSchema = new mongoose.Schema({
  productType: {
    type: String,
    required: true,
    enum: ['A', 'B'],
  },
  updated: {
    type: Date,
    default: Date.now,
    index: true,
  },
  waferId: {
    type: String,
    required: true,
    trim: true,
    minlength: 7,
  },
  sublotId: {
    type: String,
    required: true,
    trim: true,
    minlength: 7,
  },
}

// Define unique key for the schema
const Wafer = mongoose.model('Wafer', waferSchema);
module.exports.Wafer = Wafer;

我的JEST测试:

describe('API: /WT', () => {
  // Happy Path for Posting Object
  let wtEntry = {};

  beforeEach(async () => {
    wtEntry = {
      productType: 'A',
      waferId: 'A01A001.3',
      sublotId: 'A01A001.1',
    };
    await Wafer.deleteMany({});
    // I also tried to pass in done and then call done() after the delete
  });

  describe('GET /:id', () => {
    it('Return Wafer Sort Entry with specified ID', async () => {
      // Create a new wafer Entry and Save it to the DB
      const wafer = new Wafer(wtEntry);
      await wafer.save();

      const res = await request(apiServer).get(`/WT/${wafer.id}`);
      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('productType', 'A');
      expect(res.body).toHaveProperty('waferId', 'A01A001.3');
      expect(res.body).toHaveProperty('sublotId', 'A01A001.1');
    });
}

因此,当我多次运行测试时,我总是得到的错误与重复键有关: MongoError:E11000重复键错误集合:promis_tests.promiswts索引:WaferId_1_sublotId_1 dup键:{:“ A01A001.3”,:“ A01A001.1”}

但是,如果beforeEach()正确触发,我不明白如何获得此重复的键错误。我是否试图不正确地清除收藏夹?我试过在每个回调之前将完成的元素传递给before,并在delete命令之后调用它。我也尝试过在beforeAll(),afterEach()和afterAll()中实现删除,但结果仍然不一致。我对此很困惑。我可能只是一起删除了架构键,但我想了解beforeEach()在这里发生了什么。在此先感谢您的任何建议。

2 个答案:

答案 0 :(得分:0)

如果不删除架构索引,这似乎是最可靠的解决方案。无法100%知道为什么它可以在异步等待Wafer.deleteMany({});

beforeEach((done) => {
    wtEntry = {
      productType: 'A',
      waferId: 'A01A001.3',
      sublotId: 'A01A001.1',
    };
    mongoose.connection.collections.promiswts.drop(() => {
      // Run the next test!
      done();
    });
});

答案 1 :(得分:0)

这可能是因为您实际上并未使用猫鼬必须提供的promise API。默认情况下,像deleteMany()这样的猫鼬函数不会返回promise。您将必须在函数链的末尾调用.exec()以返回承诺e.g. await collection.deleteMany({}).exec()。因此,您遇到了竞争状况。 deleteMany()还接受回调,因此您始终可以将其包装在promise中。我会做这样的事情:

describe('API: /WT', () => {
  // Happy Path for Posting Object
  const wtEntry = {
    productType: 'A',
    waferId: 'A01A001.3',
    sublotId: 'A01A001.1',
  };

  beforeEach(async () => {
    await Wafer.deleteMany({}).exec();
  });

  describe('GET /:id', () => {
    it('Return Wafer Sort Entry with specified ID', async () => {
      expect.assertions(4);
      // Create a new wafer Entry and Save it to the DB
      const wafer = await Wafer.create(wtEntry);

      const res = await request(apiServer).get(`/WT/${wafer.id}`);
      expect(res.status).toBe(200);
      expect(res.body).toHaveProperty('productType', 'A');
      expect(res.body).toHaveProperty('waferId', 'A01A001.3');
      expect(res.body).toHaveProperty('sublotId', 'A01A001.1');
    });
}

此外,请始终期待带有异步代码的断言 https://jestjs.io/docs/en/asynchronous.html

您可以在此处阅读有关猫鼬诺言和查询对象的更多信息 https://mongoosejs.com/docs/promises.html