網站搜尋

node.js - 使用 TypeORM 進行整合測試


我正在透過 Supertest 向我的開發伺服器發送請求來進行整合測試。但我在如何將資料放入資料庫時遇到麻煩。例如,在執行 GET 測試之前,我想將資料插入資料庫。但我甚至無法從 TypeORM 獲取連線:

ConnectionNotFoundError: Connection "default" was not found.

即使我能從 TypeORM 獲得連接,我如何在交易中包裹測試,並在測試完成後回滾交易,以確保整合測試不會影響真實資料庫。

基本上,有沒有任何套件類似於 Rails 的 factory_bot?

describe("Templates", (): void => {
  describe("GET /api/v1/templates/{templateHash}", (): void => {
    let template: Template;
    beforeEach(
      async (): Promise<void> => {
        let templateService: TemplateService = new TemplateService();
        let connection: Connection = getConnection("default");
        template = new Template(Buffer.from(faker.random.words()), faker.random.uuid(), faker.system.fileName());
        await templateService.create(connection, template);
      },
    );
    it("should return a template", (done): void => {
      request(config.devEnvEndpoint)
        .get(`api/v1/templates/${template.templateHash}`)
        .set("Accept", "application/json")
        .expect(200)
        .end((err, response): void => {
          console.log(response);
          done();
        });
    });
  });
});

答案#1

看起來 typeorm 沒有讀取到你的配置。我建議使用 ormconfig.json 文件,並擁有兩個資料庫配置——一個用於開發,一個用於測試。

擁有兩個資料庫後,你就不需要擔心交易,並且可以在測試之間刪除資料庫。我想交易會更快,但這真的取決於你的使用情況(我注意到在進行大量 connection.synchronize() 呼叫時,測試變得慢得多)。

那麼你可以使用環境變數來決定要實例化哪個連接:

// db.ts
import { Connection, createConnection } from 'typeorm'

let connection: Connection | null = null

export async function getConnection() {
  if (connection) {
    return connection;
  }

  // DATABASE_CONFIG can be 'development' or 'test'
  // and should correspond to the connection names
  // in the ormconfig.json file
  connection = await createConnection(process.env.DATABASE_CONFIG);

  return connection;
}

export async function closeConnection() {
  await connection?.close();
}

然後你可以設定環境變數並運行你的測試:

// DATABASE_CONFIG=test yarn test
import { getConnection, closeConnection } from './db'

let connection: Connection;

beforeAll(async () => {
  connection = await getConnection();
});

beforeEach(async () => {
  // Drop everything and recreate db
  await connection.synchronize(true);
});

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

it('should create a connection', () => {
  expect(connection).toBeDefined();
})