Sequelize is a great library, but its documentation leaves a lot to be desired.
Recently, while writing unit tests for an e-commerce site project, I came across this cryptic error:
SequelizeBaseError: insert or update on table "reviews" violates foreign key constraint "reviews_user_id_fkey"
From the error, it's not too clear what has gone wrong.
The model I was testing had two associations, using Sequelize's belongsTo
method.
Sequelize generates setter methods with the name of the associated model. For example, the association Review.belongsTo(User)
will generate a method setUser()
.
Our Review would now have an integer id of the associated model.
I assumed that I could fake associations by calling review.setUser()
with an integer directly, even though no model in the database had that id. Nope!
Here's the problematic test:
...
describe('association checks', () => {
it('sets userId', () => {
return Review.create(testReview) // object defined elsewhere
.then(review => {
return review.setUser(1)
})
.then(review => {
expect(review.user_id).to.exist
expect(review.user_id).to.equal(1)
return review.setMagnet(1)
})
.then(review => {
expect(review.magnet_id).to.exist
expect(review.magnet_id).to.equal(1)
})
})
})
...
It turns out that to call the setAssociation method, you'll need to create actual records in your database.
How I fixed it:
describe('Review', () => {
let testReview = {}
before('Await database sync', () => db.didSync)
afterEach('Clear the tables', () => db.truncate({ cascade: true }))
beforeEach(function() {
testReview = {
rating: 4.5,
comment: 'A decent magnet!'
}
User.create({
name: 'Zach',
email: '[email protected]'
})
.catch(err => console.error(err))
Magnet.create({
quote: 'Many a test has failed',
price: 3.95,
image: 'cdn.shopify.com/s/files/1/0273/4903/products/ralph-waldo-emerson-fridge-magnet-1_large.jpg?v=1380467104',
title: 'Koans about Testing',
description: 'Amazing magnet with Koans from testing',
itemNumber: 12345,
size: [2, 4],
mood: ['zany', 'moody']
})
.catch(err => console.error(err))
})
Now the test will work. You'll have actual data to call your setAssociation method on.
This really helped me out, thanks for writing this!