【问题标题】:How to handle foreign key constraint with Jest/Supertest/Knex/Postgres如何使用 Jest/Supertest/Knex/Postgres 处理外键约束
【发布时间】:2020-04-16 08:17:26
【问题描述】:

我正在尝试开始为我的应用程序编写测试。我正在使用 Jest & Supertest 来运行我的所有测试。当我尝试运行我的测试套件时,我收到关于外键约束的错误。

错误:

error: truncate "users" restart identity - cannot truncate a table referenced in a foreign key constrainterror: cannot truncate a table referenced in a foreign key constraint

这是我的 server.spec.js 文件:

const request = require('supertest');
const server = require('./server.js');
const db = require('../data/db-config.js');

describe('server.js', () => {
    describe('POST /register', () => {
        it('should return 201 created', async () => {
            const user = 
                { 
                    name: "test",
                    username: "test",
                    email: "test77@test.com",
                    password: "password"
                }
            const res = await request(server).post('/api/auth/register').send(user);
            expect(res.status).toBe(201);
        })

        beforeEach(async () => {
            await db("graphs").truncate();
            await db("users").truncate();
          });
    })
})

这是我的 knex 迁移文件:

exports.up = function(knex) {
  return (
      knex.schema
        .createTable('users', tbl => {
            tbl.increments();
            tbl.string('username', 255).notNullable();
            tbl.string('password', 255).notNullable();
            tbl.string('name', 255).notNullable();
            tbl.string('email', 255).unique().notNullable();
        })
        .createTable('graphs', tbl => {
          tbl.increments();
          tbl.string('graph_name', 255).notNullable();
          tbl.specificType('dataset', 'integer[]').notNullable();
          tbl
            .integer('user_id')
            .unsigned()
            .notNullable()
            .references('id')
            .inTable('users')
            .onDelete('CASCADE')
            .onUpdate('CASCADE');
        })
  )
};

exports.down = function(knex) {
  return (
      knex.schema
        .dropTableIfExists('graphs')  
        .dropTableIfExists('users')
  )
};

我在研究中发现了这个答案:How to test tables linked with foreign keys?

我对 Postgres 和测试都是新手。我需要像在迁移中那样以相反的顺序删除表是有道理的。但是,当我尝试在测试的 beforeEach 部分截断它们时,这些表的列出顺序似乎并不重要。

我不确定从这里到底该去哪里。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript node.js postgresql jestjs knex.js


    【解决方案1】:

    我认为这里的诀窍是使用一点knex.raw

    await db.raw('TRUNCATE graphs, users RESTART IDENTITY CASCADE');
    

    CASCADE 因为你不希望外键约束妨碍,RESTART IDENTITY 因为默认 Postgres 行为不是重置序列。见TRUNCATE

    当我们讨论一个相关主题时,请允许我介绍一些可能会让您的生活更轻松的东西:模板数据库!模板是 Postgres 可以用来非常快速地从已知状态重新创建数据库(通过复制它)的数据库。这甚至比截断表还要快,而且它允许我们在测试时跳过所有烦人的外键内容。

    例如,您可以使用raw 执行以下操作:

    DROP DATABASE testdb;
    CREATE DATABASE testdb TEMPLATE testdb_template;
    

    这是一个非常便宜的操作,非常适合测试,因为您可以在每次进行测试运行时从已知状态(不一定是空状态)开始。我想需要注意的是,您的knexfile.js 将需要指定与具有足够凭据以创建和删除数据库的用户的连接(因此可能是仅知道localhost 的“管理员”连接)并且必须创建模板并且保持。请参阅Template Databases 了解更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 2019-02-20
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      • 2022-08-22
      • 1970-01-01
      相关资源
      最近更新 更多