sequelize.sync ({force: true}) иногда не может правильно настроить базу данных

1

Я пытаюсь настроить тестовое оборудование с помощью Sequelize и PostgreSQL. Однако те тесты, которые я написал, иногда проходят, а иногда терпят неудачу. Диапазон ошибок от SequelizeDatabaseError: type "participants_id_seq" already exists для SequelizeUniqueConstraintError: Validation error для SequelizeDatabaseError: relation "participants" does not exist, что заставляет меня думать, что либо я настроил ожидание неправильно, либо настроил синхронизация некорректна. Я попытался использовать async/wait, и я также попытался настроить Promises с обратными вызовами без везения.

Перед каждым тестом я вызываю sync({ force: true }), например

const { sequelize, participants: Participants } = require('../../models');

const existingUserCredentials = {
  teamName: 'TeamName',
  firstName: 'FirstName',
  lastName: 'LastName',
  email: '[email protected]',
  password: 'helloworld',
};

const Fixture = async () => {
  try {
    await sequelize.sync({ force: true });
    await Participants.create(existingUserCredentials);
  } catch (err) {
    logger.error(err);
    throw err;
  }
};

module.exports = {
  Fixture
};

Затем я вызываю это в своих тестовых случаях:

describe('POST /login', () => {
  beforeEach(async () => {
    await Fixture();
  });

  it('throws unauthorized when user does not exist', async () => {
    const { body, status } = await request(app)
      .post('/api/login')
      .send({
        email: '[email protected]',
        password: 'hunter123',
      });

    expect(body).toEqual({
      message: messages.INVALID_LOGIN_CREDENTIALS,
    });
    expect(status).toEqual(HttpStatus.UNAUTHORIZED);
  });
});

Этот тест пройдет некоторое время, и в противном случае это приведет к разным ошибкам.

Моя модель выглядит так:

const bcrypt = require('bcryptjs');

module.exports = (sequelize, DataTypes) => {
  const Participant = sequelize.define('participants', {
    teamName: {
      type: DataTypes.STRING,
      allowNull: true,
    },
    firstName: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    lastName: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
      set(password) {
        const hash = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
        this.setDataValue('password', hash);
      },
    },
  });

  Participant.verifyPassword = (password, hash) =>
    bcrypt.compareSync(password, hash);

  return Participant;
};

и моя миграция выглядит так

module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.createTable('participants', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      teamName: {
        type: Sequelize.STRING,
        allowNull: true,
      },
      firstName: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      lastName: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      email: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      password: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      createdAt: {
        allowNull: false,
        type: 'TIMESTAMP',
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
      },
      updatedAt: {
        allowNull: false,
        type: 'TIMESTAMP',
        defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
      },
    }),
  down: (queryInterface) => queryInterface.dropTable('participants'),
};

Я правильно настраиваю это, чтобы у меня была чистая база данных для каждого теста? Спасибо за помощь!

Теги:
jestjs
sequelize.js

1 ответ

1

Обновить

Я понял. Оказывается, что Jest запускает тестовые примеры параллельно, поэтому тестовая база данных использовалась одновременно несколькими тестовыми примерами. Реальное решение состоит в том, чтобы последовательно запускать тестовые --runInBand флаг --runInBand к команде test

// package.json
{
    ...
    "scripts": {
        ...
        "test": "cross-env NODE_ENV=test jest --runInBand"
    }
    ...
}

Однако это замедляет время, необходимое для запуска ваших тестовых случаев. Лучшим решением, вероятно, было бы издеваться над вашей базой данных, а не использовать фактическую тестовую базу данных. Там есть несколько вещей, таких как sequelize-mock и sequelize-mocking.


Таким образом, я не смог понять это с помощью PostgreSQL. Вместо этого я переключил конфигурацию Sequelize на использование SQLite для тестирования, и это сработало. Здесь моя конфигурация

module.exports = {
  development: {
    username: process.env.PGUSER,
    password: process.env.PGPASSWORD,
    database: process.env.PGDATABASE,
    host: process.env.PGHOST || '127.0.0.1',
    dialect: 'postgres',
    operatorsAliases: false,
  },
  test: {
    username: process.env.SQLITEUSER,
    password: process.env.SQLITEPASSWORD,
    database: process.env.SQLITEDATABASE,
    host: process.env.PGHOST || '127.0.0.1',
    dialect: 'sqlite',
    operatorsAliases: false,
  },
  production: {
    username: process.env.PGUSER,
    password: process.env.PGPASSWORD,
    database: process.env.PGPRODDATABASE,
    host: process.env.PGHOST || '127.0.0.1',
    dialect: 'postgres',
    operatorsAliases: false,
    logging: false,
  },
};

Я собираюсь оставить этот вопрос открытым, хотя, поскольку я действительно не думаю, что это хорошее решение

Ещё вопросы

Сообщество Overcoder
Наверх
Меню