Как структурировать лямбда-код для тестируемости - PullRequest
1 голос
/ 28 марта 2019

Я пытаюсь создать небольшой REST API с API-шлюзом, lambda и DynamoDB, следуя при этом хорошим методам разработки, таким как TDD.Я привык иметь возможность использовать DI-контейнер для предоставления своих объектов, что идеально подходит для макетирования и тестирования.В инфраструктуре MVC была бы единственная точка входа, где я мог бы определить конфигурацию своего контейнера, загрузить приложение и вызвать контроллер для обработки события.Я мог бы протестировать контроллер независимо от остальной части приложения и ввести поддельные зависимости.Я не могу понять, как отделить зависимости, которые лямбда-функция может иметь от самой лямбда-функции.Например:

const { DynamoDB } = require('aws-sdk')
const { UserRepo } = require('../lib/user-repo')

const client   = new DynamoDB({ region: process.env.REGION }) // Should be resolved by DI container
const userRepo = new UserRepo(client) // Should be resolved by DI container

exports.handler = async (event) => {
  return userRepo.get(event.id)
}

Кто-нибудь может привести меня в правильном направлении для структурирования лямбда-кода, чтобы его можно было правильно протестировать на модуле?

1 Ответ

2 голосов
/ 28 марта 2019

Один из способов, которым мы подошли к этому в проекте, над которым я сейчас работаю, - это разделение требований, поэтому 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, которое гарантирует, что вся система работает вместе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...