You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改AWS Lambda单元测试以使用Mock Elasticsearch索引?

问题描述

我正在测试一个从elasticsearch查询并返回数据的AWS Lambda函数。
我已经掌握了创建Mock elasticsearch及向Mock索引添加数据的方法,代码如下:

const { Client } = require('@elastic/elasticsearch')
const Mock = require('@elastic/elasticsearch-mock')

const mock = new Mock()
const client = new Client({
  node: 'http://localhost:9200',
  Connection: mock.getConnection()
})

mock.add({
  method: 'POST',
  path: '/indexName/_search',
  body: { query: { match: { foo: 'bar' } } }
}, () => {
  return {
    hits: {
      total: { value: 0, relation: 'eq' },
      hits: []
    }
  }
})

现在的问题是:如何对查询Mock数据的端点进行单元测试?相关文档很少。具体来说,如何修改下面的单元测试代码,让它用上面创建的Mock Elasticsearch索引,替代当前用Docker等部署的真实elasticsearch实例来测试?

const mock = (
  partial: Partial<APIGatewayProxyEvent>
): APIGatewayProxyEvent => partial as APIGatewayProxyEvent;
const mockContext = {} as Context;
const mockCallback: Callback<APIGatewayProxyResult> = () => {
  return;

describe('lambda handler', () => {



  it('returns response', async () => {
    const result = await handler(
      mockEvent({ queryStringParameters: { name: 'dave' } }),
      mockContext,
      mockCallback
    );
    if (!result) {
      fail('no result');
    } else {
      expect(result.statusCode).toEqual(200);
      expect(JSON.parse(result.body)).toEqual(mockResponse);
    }
  });
});
};
解决方案

核心思路是在单元测试中注入Mock Elasticsearch客户端,替代Lambda函数里原本创建的真实ES客户端,具体步骤如下:

1. 重构Lambda函数,支持客户端注入

先把Lambda的ES客户端创建逻辑抽离,允许外部传入自定义客户端,避免硬编码:

import { Client } from '@elastic/elasticsearch';
import { APIGatewayProxyEvent, Context, Callback, APIGatewayProxyResult } from 'aws-lambda';

// 抽离客户端创建逻辑,支持外部传入Mock客户端
const createEsClient = (client?: Client) => {
  return client || new Client({ node: process.env.ES_NODE });
};

export const handler = async (
  event: APIGatewayProxyEvent,
  context: Context,
  callback: Callback<APIGatewayProxyResult>,
  esClient?: Client // 新增可选参数,用于注入Mock客户端
): Promise<APIGatewayProxyResult | void> => {
  const client = createEsClient(esClient);
  // 原有查询逻辑(示例)
  const response = await client.search({
    index: 'indexName',
    body: { query: { match: { name: event.queryStringParameters?.name } } }
  });

  return {
    statusCode: 200,
    body: JSON.stringify(response.hits.hits)
  };
};

2. 修改单元测试,注入Mock客户端

在测试用例中初始化Mock ES客户端,配置预期查询的响应,然后传给handler:

import { handler } from './your-lambda-file';
import { Client } from '@elastic/elasticsearch';
import { Mock } from '@elastic/elasticsearch-mock';
import { APIGatewayProxyEvent, Context, Callback } from 'aws-lambda';

const mockEvent = (partial: Partial<APIGatewayProxyEvent>): APIGatewayProxyEvent => partial as APIGatewayProxyEvent;
const mockContext = {} as Context;
const mockCallback: Callback = () => {};

// 定义测试预期的Mock响应数据
const mockResponse = [
  { _source: { name: 'dave', foo: 'bar' } }
];

describe('lambda handler', () => {
  it('returns response with mock ES data', async () => {
    // 创建Mock客户端并配置查询匹配规则
    const mock = new Mock();
    const mockEsClient = new Client({
      node: 'http://localhost:9200',
      Connection: mock.getConnection()
    });

    // 匹配Lambda中实际执行的查询(path、body需与Lambda代码完全一致)
    mock.add({
      method: 'POST',
      path: '/indexName/_search',
      body: { query: { match: { name: 'dave' } } }
    }, () => {
      return {
        hits: {
          total: { value: 1, relation: 'eq' },
          hits: mockResponse
        }
      };
    });

    // 调用handler时注入Mock客户端
    const result = await handler(
      mockEvent({ queryStringParameters: { name: 'dave' } }),
      mockContext,
      mockCallback,
      mockEsClient
    );

    // 断言结果符合预期
    expect(result).toBeDefined();
    expect(result?.statusCode).toEqual(200);
    expect(JSON.parse(result?.body || '')).toEqual(mockResponse);
  });
});

3. 关键注意事项

  • 确保Mock的method、path、body与Lambda中执行的ES查询完全匹配,否则Mock不会触发。
  • 若有多个查询场景,可在测试用例中添加多个mock.add规则分别匹配。
  • 测试过程完全脱离真实ES实例,保证单元测试的独立性和执行速度。

内容的提问来源于stack exchange,提问作者user6248190

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:48:19