Sean Kelly
Sean Kelly

Reputation: 991

How to write unit tests for sequelize models with Chai

My tests are working and passing, but chai's done function is messing up. I've tried a few different methods, but I don't understand where I'm going wrong in these unit tests. I'm very new to unit testing and chai, so any help would be greatly appreciated

The places where the test is failing: line 40 (create), line 98 (update)

Any ideas?

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: "[email protected]",
        }

        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()
                    })
                })

            })
        })
    })    
});

Upvotes: 1

Views: 8901

Answers (2)

vapurrmaid
vapurrmaid

Reputation: 2307

@mcranston18 left a really nice detailed accepted answer.

What I'd like to add for others that find the question or for OP in the future, is the use of 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 (...)
  })
})

Here's a really simple way to create then update using 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')
  })
})

Upvotes: 3

mcranston18
mcranston18

Reputation: 4790

There are two things to keep in mind:

(1) Sequelize uses promises for its ORM methods. So, even after you are calling destroy, you need to attach a callback, e.g.:

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

(2) The done method in chai should be attached to each test, as opposed to the test block:

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
    });
  });
});

In your case, here are the two failing test cases:

// 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()
              })
          })
      })
  })
})

Upvotes: 4

Related Questions