Skip to content

Instantly share code, notes, and snippets.

@mltsy
Last active April 12, 2024 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mltsy/629d2b5b703f14e3e97eb8396518cfad to your computer and use it in GitHub Desktop.
Save mltsy/629d2b5b703f14e3e97eb8396518cfad to your computer and use it in GitHub Desktop.
Monkey Patch for the unfriendly errors thrown by Sequelize 6
/**
* This monkey patch fixes an error reporting issue with sequelize errors in tests,
* which was fixed in Sequelize v7, but hasn't been back-ported to Sequelize v6.
* See https://github.com/sequelize/sequelize/issues/14807#issuecomment-1854398131
*
* It should only be used in the test env, to make Sequelize error messages show up.
* This can be removed when we upgrade to Sequelize 7, or when the issue is fixed in v6.
*/
const { Sequelize } = require('sequelize')
const sequelizeVersion = Sequelize['version'] || '6.x.x' // doesn't (currently) exist in v6
const major = Number(sequelizeVersion.split('.')[0])
if (major >= 7) {
console.warn(
'This patch was probably made redundant in Sequelize v7, you should check!'
)
}
/**
* @param {Sequelize} instance An instance of Sequelize
* @returns {Sequelize} Monkey-patched Sequelize instance that throws Jest-compatible errors
*/
function monkeyPatchSequelizeErrorsForJest(instance) {
if (typeof jest === 'undefined') return instance
const origQueryFunc = instance.query
instance.query = async function query(...args) {
let result
try {
result = await origQueryFunc.apply(this, args)
} catch (err) {
throw fixSequelizeError(err)
}
return result
}
return instance
}
const isSequelizeError = e =>
e instanceof Error && e.name.startsWith('Sequelize')
const fixSequelizeError = error => {
if (!isSequelizeError(error)) return error
let { message } = error.parent
if (error.sql) {
message += '\nSQL: ' + error.sql
}
if (error.parameters) {
const stringifiedParameters = JSON.stringify(error.parameters)
if (
stringifiedParameters !== 'undefined' &&
stringifiedParameters !== '{}'
) {
message += '\nParameters: ' + stringifiedParameters
}
}
message += '\n' + error.stack
error.message = message
Error.captureStackTrace(error)
return error
}
module.exports = monkeyPatchSequelizeErrorsForJest
@mltsy
Copy link
Author

mltsy commented Apr 11, 2024

A workaround for sequelize/sequelize#14807

This should cause errors to have the correct stack trace and error name, such that Jest will print out the error that occurred.
To use this, just import it wherever you define your Sequelize DB, and do something like:

    const monkeyPatchSequelizeErrorsForJest = require('./monkeyPatchSequelizeErrorsForJest')

    if (process.env.NODE_ENV === "test") {
      return monkeyPatchSequelizeErrorsForJest(sequelize)
    } else {
      return sequelize
    }

(It will always reference the monkeyPatch file as the source of the error, but you can look down the stack trace to find the real source)

@mltsy
Copy link
Author

mltsy commented Apr 11, 2024

Updated so that the error thrown is actually the original error class, not a new invented one (since validating the class of the error thrown may be important for some tests)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment