Один из способов, которым мы подошли к этому в проекте, над которым я сейчас работаю, - это разделение требований, поэтому handler
отвечает за:
- Создание клиентов;
- Извлечение любого конфига из окружения; и
- Получение параметров из события.
Затем он вызывает другую функцию, которая выполняет большую часть работы и которую мы можем тестировать изолированно. Думайте о handler
как о контроллере, а о другой функции - как о сервисе, который выполняет работу.
В вашем конкретном случае это может выглядеть так:
const { DynamoDB } = require('aws-sdk');
const { UserRepo } = require('../lib/user-repo');
const doTheWork = (repo, id) => repo.get(id);
exports.handler = async (event) => {
const client = new DynamoDB({ region: process.env.REGION });
const userRepo = new UserRepo(client);
return doTheWork(userRepo, event.id);
}
doTheWork
теперь можно выполнять на уровне юнита, используя удвоение теста для объекта репо и любых вводимых вами данных. UserRepo
уже отделен внедрением в конструктор клиента Dynamo, так что это тоже должно быть довольно тестируемым.
У нас также есть тесты на уровне интеграции, которые только макетируют AWS SDK (вы можете альтернативно использовать насмешку транспортного уровня или что-то вроде aws-sdk-mock
) плюс тестирование E2E, которое гарантирует, что вся система работает вместе.