Написание серверного кода — например, веб-сервисов или чего-то еще — с помощью функций AWS Lambda невероятно просто, особенно когда вы выбираете Node.js в качестве своего предпочтительного оружия. Количество кода, необходимого для запуска, настолько мало, что кажется почти волшебным. Однако по мере того, как вы строите свою лямбду, сложность быстро поднимает голову, и вскоре вы почувствуете необходимость добавить несколько тестов.
Модульное тестирование является частью рабочего процесса любого хорошего разработчика, но я считаю, что оно особенно важно при работе с языками с динамической типизацией, такими как ванильный Javascript. Его свободная типизация делает разработку быстрой, но также создает определенную степень неопределенности при внесении изменений или рефакторинге. Хорошее тестовое покрытие может компенсировать это и позволить вам работать быстрее. Если вы сможете имитировать зависимости вашей Lambda, вы будете вполне уверены, что ваш успешный модульный тест представляет собой конечный производственный код.
Внедрение зависимости
«Внедрение зависимостей» — это несколько пугающий термин, используемый в разработке программного обеспечения для описания чего-то довольно простого:
Внедрение зависимостей — это метод программирования, который делает класс независимым от его зависимостей. Это достигается путем отделения использования объекта от его создания.
Это наиболее полезно при применении в контексте модульного тестирования, поскольку позволяет вам имитировать зависимости, которые не должны быть активны во время тестов.
В функциях Node.js Lambda зависимости импортируются с помощью функции require(). Он создает константу в области видимости функции, указывающую на какой-то внешний код. По умолчанию вы делаете это на верхнем уровне вашего файла Node.js, эффективно делая зависимость глобально доступной для указанного файла. Рассмотрим этот фрагмент, где мы импортируем AWS SDK и создаем новый экземпляр DynamoDB DocumentClient:
const AWS = require('aws-sdk') const documentClient = new AWS.DynamoDB.DocumentClient()
Что происходит, когда вы используете код модульного тестирования, который импортирует указанную выше зависимость? В этом случае ваш тест установит активное соединение с DynamoDB и, возможно, начнет чтение и запись данных в нее! Хотя вы можете возразить, что это тест сам по себе, эта ситуация далека от идеальной. Каждый вызов модульного теста будет
- потенциально нести расходы
- записывать данные в действующую базу данных, возможно, нарушая ее согласованность
- быть медленным
Пост Ричарда Хаятта Medium от 2016 года актуален и сегодня, поскольку в нем описывается, как сделать загрузку зависимостей асинхронной и внедряемой с помощью экспорта. объект для хранения и ссылки на зависимости.
exports.deps = () => { const AWS = require('aws-sdk') const documentClient = new AWS.DynamoDB.DocumentClient() return Promise.resolve({ dynamoBatchWrite: params => documentClient.batchWrite(params).promise() }) }
Фактический импорт зависимостей заключен в область действия функции deps и делается асинхронным путем помещения словаря результатов в промис. Эта асинхронность позволяет нам перезаписывать функцию deps во время тестов, оставляя ее как есть в рабочей среде.
Рабочий код будет просто ждать зависимостей вверху, после чего вы сможете получить доступ к полностью построенным зависимостям:
exports.handler = async event => { const deps = await exports.deps() ... }
Теперь для теста:
require('chai').should() const lambda = require('../index') const sinon = require('sinon') describe('importOPML', () => { beforeEach('mock dependencies', () => { const mockWriter = sinon.mock() mockWriter.resolves({ UnprocessedItems: [] }) lambda.deps = () => Promise.resolve({ dynamoBatchWrite: mockWriter }) }) it('should succeed with empty opml', async () => { // Using lambda here, will call the version that uses the mocked DynamoDB writer. } })
Это тест Chai, в котором Синон используется для насмешек, но предпосылка та же. Перед запуском каждого тестового блока выполняется блок beforeEach, который подготавливает лямбду с фиктивными зависимостями.
Вот и все. Вы отправляетесь на гонки!
Первоначально опубликовано на jarroo.com 9 декабря 2018 г.