使用 jest 和 ts-jest 模拟 @aws-sdk/client-dynamodb 模块时的奇怪行为

时间:2021-03-11 05:41:34

标签: typescript jestjs amazon-dynamodb ts-jest

我在模拟模块时遇到了一个奇怪的问题,尤其是 waitForTableExists 模块中的 @aws-sdk/client-dynamodb。在给定的测试用例中,由于某种原因,waitForTableExists 执行实际代码而不是模拟代码。但是,正确模拟了 DynamoDBClient 类。我不确定我哪里出错了。

dynamodb.ts 包含要测试的函数。为简洁起见,文件的其他部分未显示。

// other code not shown ...

async function ifIsActive<R>(
  client: DynamoDBClient,
  f: () => R,
): Promise<R | undefined> {
  try {
    await waitForTableExists(
      { client, maxWaitTime: 30 },
      { TableName: 'a-table-name' },
    );
    return f();
  } catch (error) {
    logger.error(error, 'Error in waitForTableExists()');
  }
}

export async function getItem(
  client: DynamoDBClient,
): Promise<Config | undefined> {
  async function f() {
    const command = new GetItemCommand(...);
    try {
      const { Item } = await client.send(command);
      return Item;
    } catch (error) {
      logger.error(error, `An error occurred when trying to get an item`);
    }
    return undefined;
  }
  return await ifIsActive(client, f);
}

部分 dynamodb.spec.ts 如下所示。


beforeEach(() => {
  jest.resetAllMocks();
  jest.resetModuleRegistry();
});

// other describes test cases not shown ...

describe('getItem()', () => {
  beforeEach(() => {
    jest.mock('@aws-sdk/client-dynamodb');
  });

  test('existing item', async () => {
    const { DynamoDBClient, waitForTableExists } = await import('@aws-sdk/client-dynamodb');
    const waitForTableExistsMock = mocked(waitForTableExists);
    waitForTableExistsMock.mockImplementation(async () => {
      console.log('>>>>> waitForTableExists mock 1');  // this never happens
      return { state: WaiterState.SUCCESS };
    })
    const DynamoDBClientMock = mocked(DynamoDBClient, true);
    const sendMock = DynamoDBClientMock.prototype.send;
    send.mockImplementation(() = > {
      console.log(`>>>>> send mock 1`);  // this is printed to console output
      return {Table:{TableStatus:'ACTIVE'}};
    })
    const client = new DynamoDBClient({});

    const item = await getItem(client, 'an-existing-id');

    expect(send).toBeCalledTimes(1);
    expect(waitForTableExistsMock).toBeCalledTimes(1);
    // other expect ...
  });

@aws-sdk/client-dynamodb中,函数waitForTableExists如下。

export const waitForTableExists = async (
  params: WaiterConfiguration<DynamoDBClient>,
  input: DescribeTableCommandInput
): Promise<WaiterResult> => {
  const serviceDefaults = { minDelay: 20, maxDelay: 120 };
  return createWaiter({ ...serviceDefaults, ...params }, input, checkState);
};

0 个答案:

没有答案