重用 Jest 单元测试

Gur*_*sad 11 javascript unit-testing jestjs

我正在尝试使用 Jest 测试几个数据库实现。为了帮助测试这些实现,我首先针对两个实现都预期实现的 API 提出了一组单元测试。

我目前正在努力将这两个实现传递给测试套件。

以下是最简单形式的(虚拟)MongoDB 实现:

class MongoDB {
  async query () {
    console.warn(`This is a dummy function.`)
  }

  async connect () {
    // The real connect takes some time..instead we just simulate it
    await new Promise((resolve, reject) => {
      setTimeout(resolve, 300)
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的测试的一小部分:

let db
beforeAll(async () => {
  db = new MongoDB()
  await db.connect()
  console.log(`mongoDB ready`)
})

async function testDB (db) {
  describe('Basic', async () => {
    test('Valid instance', async () => {
      expect(db).toBeTruthy()
      expect(db.query).toBeTruthy()
    })
  })
}

describe('Tests', async () => {
  console.log(`Running testDB`)
  testDB(db) // Have also unsuccessfully tried changing this to: return testDB(db)
})
Run Code Online (Sandbox Code Playgroud)

我使用这种方法的目标是将所有测试包装在testDB函数中,并使用各种实现简单地调用它。例如,testDB(new MongoDB())testDB(new MemoryDB())等。

然而,这似乎并没有像预期的那样工作。上面的代码导致一个错误,指出:

  ? Tests › Basic › Valid instance

    expect(received).toBeTruthy()

    Expected value to be truthy, instead received
      undefined
Run Code Online (Sandbox Code Playgroud)

console.log语句的顺序似乎表明测试 db初始化之前正在运行。

  console.log mongo.test.js:20
    Running testDB

  console.log mongo.test.js:7
    mongoDB ready
Run Code Online (Sandbox Code Playgroud)

可以在 repl.it复制整个示例以及结果输出。

如何重用单元测试来测试多个实现而无需重复测试和维护两个版本?

mur*_*adm 11

今天面临同样的需求。这是改编自打字稿的方式,但您明白了:

// common/service.test.js
export const commonServiceTests = (name, impl) => {
  describe(`Common tests for ${implName}`, () => {
    // pile your tests here
    test('test1', () => { ... });
    test('test2', () => { ... });
    test('test3', () => { ... });
  });
}

// just to avoid warning, that no tests in test file
describe('Common tests for CommonService implementations', () => {
  test('should be used per implementation', () => {});
});
Run Code Online (Sandbox Code Playgroud)

对于您的每个实现:

// inmemory/service.test.js
import { commonServiceTests } from '../common/service.test';
import ...; // your implementation here

const myInMemoryService = ...; // initialize it

commonServiceTests('InMemory', myInMemoryService);
Run Code Online (Sandbox Code Playgroud)

然后common/service.test.js将在每个实现测试中执行中定义的所有测试。

如果您的初始化是async(最有可能的),那么您的共享测试也应该是async。然后:

// common/service.test.js
export const commonServiceTests = (name, impl: Promise) => {
  describe(`Common tests for ${implName}`, () => {
    // pile your async tests here
    test('test1', async () => {
      const svc = await impl;
      return await svc.doSomthingPromisy();
    });
    test('test2', () => { ... });
    test('test3', () => { ... });
  });
}
Run Code Online (Sandbox Code Playgroud)