可以开玩笑地测试一下吗?

时间:2019-09-05 18:37:25

标签: javascript jestjs es6-promise

据我了解,使用await方法( thenable then来对象只是调用then方法。我无法通过玩笑来使它起作用:

test('test thenable', async () => {
  const thenable = {
    then: () => 1
  };
  const actual = await thenable;
  expect(actual).toEqual(1);
});

这会引发一个开玩笑的错误:

  

超时-在jest.setTimeout.Error指定的5000ms超时内未调用异步回调

是否可以通过异步测试 thenable 对象?

背景

我正在尝试测试已配置的knex querybuilder。我正在测试的代码是这样的:

const query = db('my_table')
  .where('key', 'someValue')
  .select('key', 'value');
const results = await query;

db变量是一个已配置的Knex对象,用于标识客户端和配置。

因此,db是使用whereselect方法返回对象的函数,并且它必须具有then方法,因此可以await编辑。至少我是这样理解它的。

2 个答案:

答案 0 :(得分:0)

这是一个解决方案,例如,我们在findById类中有一个SomeDaoImpl方法,并在该方法中使用了knex查询构建器。我使用IKnex界面来模拟knex查询构建器的真实界面。

index.ts

interface IKnex {
  where(...args: any): any;
  raw(...args: any): any;
  select(...args: any): any;
  then(): any;
}

class SomeDaoImpl {
  private knex: IKnex;
  constructor({ knex }) {
    this.knex = knex;
  }
  public findById(id: string) {
    return this.knex.where({ id }).select();
  }
}

export { SomeDaoImpl, IKnex };

您可以模拟knex查询构建器的链接方法,如下所示:

index.spec.ts

import { SomeDaoImpl, IKnex } from './';

const knexMocked: jest.Mocked<IKnex> = {
  where: jest.fn().mockReturnThis(),
  raw: jest.fn().mockReturnThis(),
  select: jest.fn().mockReturnThis(),
  then: jest.fn().mockReturnThis()
};

const someDaoImpl = new SomeDaoImpl({ knex: knexMocked });

describe('SomeDaoImpl', () => {
  it('t1', async () => {
    (knexMocked.where() as jest.Mocked<IKnex>).select.mockResolvedValueOnce('mocked data');
    const actualValue = await someDaoImpl.findById('1');
    expect(actualValue).toBe('mocked data');
    expect(knexMocked.where).toBeCalledWith({ id: '1' });
    expect(knexMocked.where().select).toBeCalledTimes(1);
  });
});

单元测试结果:

 PASS  src/stackoverflow/57811289/index.spec.ts
  SomeDaoImpl
    ✓ t1 (12ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.033s

完整的演示在这里:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57811289

答案 1 :(得分:0)

是的,Jest可以使用async测试 thenable 对象。

then函数应接受success回调,还可以接受error回调。

当前编写代码的方式then不接受任何参数,因此它永远不会调用success回调...因此它永远不会解析,await会继续等待直到测试超时。

要解决此问题,只需添加一个success参数并使用已解析的值对其进行调用:

test('test thenable', async () => {
  const thenable = {
    then: success => { success(1); }
  };
  const actual = await thenable;
  expect(actual).toEqual(1);  // Success!
});