Тестирование вставок БД в Javascript с помощью async/await с использованием jest и supertest

Я пытаюсь написать тесты для стека React/Postgres, и знаете что? Работает... иногда :-(

Я использую вспомогательный файл для сброса базы данных между тестами:

// partial contents of dbtools.js
function clean_db(){
  const client = new Client(dbConfig);
  client.connect();
  client.query( 
    `TRUNCATE TABLE "templates"; 
     ALTER SEQUENCE "templates_id_seq" RESTART WITH 1;`
    )
    .catch( err => { console.error(err); } )
    .then( () => client.end() );
}

Сами тесты примерно такие:

const request = require('supertest');
const app = require('../app');
const { Client } = require('pg');
const SQL = require('sql-template-strings');
const dbConfig = require('../db');
const { clean_db } = require('./helpers/dbtool');
const faker = require('faker');

async function insertTemplate(myTemplate) {
  const client = new Client(dbConfig);
  const { name, status, version } = myTemplate;
  client.connect();
  await client.query(
    SQL`INSERT INTO templates (name, status, version )
    VALUES (${name}, ${status}, ${version})
    RETURNING id`)
    .catch( err => console.error(err) )
    .then( () => client.end() );
}

function randomTemplate() {
  return {
    name: faker.internet.userName,
    status: 'new',
    version: String(faker.random.number())
  };
}


beforeAll(async () => {
  await clean_db();
});

afterAll(async () => {
  await clean_db();
});

describe('GET /templates', () => {

  //... other tests ...

  describe('When there are 1 or more records in the table', () => {

    const templ1 = randomTemplate();
    const templ2 = randomTemplate();
    const templ3 = randomTemplate();

    beforeEach(async () => {
      await clean_db();
      const t1_added = await insertTemplate(templ1);
      const t2_added = await insertTemplate(templ2);
      const t3_added = await insertTemplate(templ3);
    });

    afterEach(async () => {
      await clean_db();
    });

    // here's one example problem child
    test('It should respond with an JSON array of records', async done => {
      const response = await request(app).get('/templates');
      expect(response.body.length).toBe(3);
      console.error(response.body);
      done();
    });

    //... more tests ...

    });
  });
});

Я подозреваю, что вставки не завершаются до запуска теста.

Ошибка, которую я возвращаю, выглядит примерно так:

 FAIL  tests/templates.test.js
  ● GET /templates › When there are 1 or more records in the table › It should respond with an JSON a
rray of records

    expect(received).toBe(expected) // Object.is equality

    Expected: 3
    Received: 2

      94 |     test('It should respond with an JSON array of records', async done => {
      95 |       const response = await request(app).get('/templates');
    > 96 |       expect(response.body.length).toBe(3);
         |                                    ^
      97 |       console.error(response.body);
      98 |       done();
      99 |     });

      at Object.toBe (tests/templates.test.js:96:36)

Есть ли что-то, что я делаю неправильно с async/await? Стратегия просто неверна?


person Dycey    schedule 24.10.2019    source источник


Ответы (1)


Я видел, что мы смешиваем async/await и обещание, что не является ненужным. Это, вероятно, виновник ошибки.

помощник может быть улучшен как

async function clean_db() {
  const client = new Client(dbConfig);

  try { // using try catch to catch error
    await client.connect(); // specify await, take a look at its doc 

    await client.query( 
      `TRUNCATE TABLE "templates"; 
       ALTER SEQUENCE "templates_id_seq" RESTART WITH 1;`
      )

     await client.end(); // specify await
  } catch (err) {
    console.error(err);
  };
}

Обратите внимание, что обещания (then) больше нет, и мы используем исключительно async/await.

insertTemplate можно улучшить, т.к.

async function insertTemplate(myTemplate) {
  const client = new Client(dbConfig);
  const { name, status, version } = myTemplate;

  try {
    await client.connect();

    await client.query(
      SQL`INSERT INTO templates (name, status, version )
      VALUES (${name}, ${status}, ${version})
      RETURNING id`)

      await client.end();
  } catch (err) {
    console.error(err)
  }
}

Ссылка: https://node-postgres.com/

person deerawan    schedule 03.12.2019
comment
Я так понимаю, что в функции clean_db() отсутствует async? - person Dycey; 04.12.2019
comment
@Dycey, да, я забыл положить туда async. Я обновил код. - person deerawan; 05.12.2019