使用jest和supertest用async / await测试Java脚本中的数据库插入

时间:2019-10-24 11:04:31

标签: javascript testing async-await jestjs 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)

异步/等待是否有我做错的事情?该策略是错误的吗?

1 个答案:

答案 0 :(得分:1)

我看到我们在异步/等待和承诺之间混合使用,这不是不必要的。这可能是该错误的元凶。

助手可以改进为

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/