如何使用 Chai 为 sequelize 模型编写单元测试

How to write unit tests for sequelize models with Chai

我的测试正常运行并通过,但 chai 的 done 函数出错了。我尝试了几种不同的方法,但我不明白我在这些单元测试中哪里出错了。我是单元测试和 chai 的新手,所以非常感谢任何帮助

测试失败的地方:第40行(创建),第98行(更新)

有什么想法吗?

const chai = require('chai')
let should = chai.should()
let expect = chai.expect
let db = require('../app/models')
db.hosts.modelName = 'Hosts'
db.victims.modelName = 'Victims'
let models = [db.hosts, db.victims]

models.forEach(model => {
    describe(`${model.modelName} Model`, function (done) {
        var modelData = {
            guest_count: 3,
            start_date: "2018-01-11T00:00:00.000Z",
            end_date: "2018-01-12T00:00:00.000Z",
            location: {
                type: "Point",
                coordinates: [
                    -74.323564,
                    40.232323
                ]
            },
            first_name: "Sean",
            last_name: "Destroyed",
            phone: "7325556677",
            address: "123 main street, red bank, nj",
            email: "test@gmail.com",
        }

        it(`should create a new ${model.modelName}`, function () {

            model.create(modelData).then(function (user) {
                //victim name should be equivalent to the fake submission we are using
                expect(user.first_name).to.equal("Sean"); 
                //remove the entry from the database
                model.destroy({
                    where: {
                        id: user.id
                    }
                })
                done()
            })


        });

        it(`should delete a ${model.modelName} from the database`, function () {
            model.create(modelData).then(function (user) {
                //victim name should be equivalent to the fake submission we are using
                //remove the entry from the database
                model.destroy({
                    where: {
                        id: user.id
                    }
                })

                try {
                    model.findOne({
                        where: {
                            id: user.id
                        }
                    })
                } catch (err) {
                    expect(user.first_name).to.undefined; 
                    if (err) {
                        done()
                    }
                }

            })
        })

          it(`should update the ${model.modelName} entry in the database`, function () {
            model.create(modelData).then(function (user) {
                //after user is created, then update a value
                modelData.guest_count = 12

                model.update(modelData, {
                    where: {
                        id: user.id
                    }
                }).then(function(data) {
                    model.findOne({
                        where: {
                            id: user.id
                        }
                    }).then(function (data) {
                        expect(data.guest_count).to.equal(12);
                    }).then(function () {
                        model.destroy({
                            where: {
                                id: user.id
                            }
                        })
                    }).then(function() {
                        done()
                    })
                })

            })
        })
    })    
});

有两点需要牢记:

(1) Sequelize 对其 ORM 方法使用承诺。因此,即使在调用 destroy 之后,您也需要附加回调,例如:

model.destroy({
  where: {
      id: user.id
  }
})
.then(function() {
  // now do something
});

(2) chai 中的 done 方法应该附加到每个测试,而不是测试块:

describe('some test block', function() {
  it('should do something,' function(done) {
    User.findAll().then(function(users) {
      // expect users to do something
      done(); // tests are done
    });
  });
});

对于您的情况,这是两个失败的测试用例:

// ensure "destroy" has a callback
it(`should create a new ${model.modelName}`, function (done) {
    model.create(modelData).then(function (user) {
        //victim name should be equivalent to the fake submission we are using
        expect(user.first_name).to.equal("Sean"); 
        //remove the entry from the database
        model.destroy({
            where: {
                id: user.id
            }
        }).then(function() {
          done();
        })  
    })
});

// update
it(`should update the ${model.modelName} entry in the database`, function () {
  model.create(modelData).then(function (user) {
      //after user is created, then update a value
      modelData.guest_count = 12

      model.update(modelData, {
          where: {
              id: user.id
          }
      }).then(function(data) {
          model.findOne({
              where: {
                  id: user.id
              }
          }).then(function (data) {
              expect(data.guest_count).to.equal(12);
          }).then(function () {
              model.destroy({
                  where: {
                      id: user.id
                  }
              }).then(function() {
                  done()
              })
          })
      })
  })
})

@mcranston18 留下了一个非常好的详细的可接受的答案。

我想为找到问题的其他人或将来的 OP 添加的是使用 async/await:

describe('some test block', function() {
  it('should do something', async function() { // notice async and no done
    const users = await User.findAll()
    // expect users.to (...)
  })
})

这是使用 async/await 创建然后更新的非常简单的方法:

describe('some test block', function () {
  it('should do something', async function () {
    const Joe = await User.create({ name: 'Jo' })  // oops
    // assertions/expect/should
    // ex: expect(Joe.name).to.equal('Jo')

    await Joe.update({ name: 'Joe' }) // that's better
    // assertions/expect/should
    // ex: expect(Joe.name).to.equal('Joe')
  })
})