Хроники изучения golang фронтендером. Приколы юнит-тестов ч1
С целью обучения я решил написать на go пользовательский сервис. Подробности пока не очень важны. Важно, что там есть модуль работы с пользователями, с которого я и начал разработку.
Для лучшего понимания ситуации важно уточнить, что для работы с БД я решил взять SQLC на PGX драйвере.
Сначала всё было просто: я поднял в докере базу, сгенерировал миграции.
Для миграций честно использовал нейронку, потому что очень уж долго было б писать миграции руками. Давно сам SQL не писал и решил сосредоточиться на go. SQL подтянуть можно будет и попозже.
Так вот, натравил миграции, накатил их гусём, сгенерировал sqlc код.
С SQLC пришлось немного погемороиться, потому что оно из коробки не цепляет переменные окружения из .env. Решил написанием небольшого скрипта в makefile.
Итак, сгенерировал код, выделил user_module, там напилил файлы под роутер, dto и под юзкейсы (читай, бизнес-логику).
Написал, зарегистрировал всё это в gin, запустил, работает. Огонь!
Сгенерировал мок под sqlc querier, в user_module подменил интерфейс, написал тесты. Всё проходит, всё огонь.
И тут я заметил. что у меня перед созданием и удалением пользователя происходит проверка на существование этого самого пользователя, но проходит оно синхронно. Решил, что нужна транзакция. А Querier интерфейс не умеет в транзакции! Пришлось возвращать в модуль объект Queries. Так становится ок, но ломаются тесты. Мы ведь подменяли в модуле интерфейс, а теперь вместо него структура...
И что делать?
Нужно вернуть интерфейс. Но в SQLC подходящего интерфейса нет. Значит нужно писать свой! Который по необходимости будет мне возвращать Querier, TxQuerier, либо создавать транзакцию. Фабрика нужна, получается.
Было не просто... В пакете db добавил пакет generated, куда сложил SQLC сгенерированный код, на уровне пакета db сделал factory, который возвращал мне необходимую фабрику. Эту фабрику вместо DB запихнул в user_module, сгенерировал к ней мок и уже в тестах всё это дело подменил.
Дальше в планах настроить правильное логирование, чтобы шаблоном и контекст запроса автоматически печатать по-шаблону, и кастомную ошибку по необходимости докидывать. но это я завтра с Запом ковыряться буду. Полагаю, что это всё конфигом решается с минимальными усилиями, но с конфигом ещё разобраться нужно...
А впереди ещё аутентификацию прикручивать... пока планирую auth и request на csrf токенах сделать, то может, для простоты, заменю на jwt. И, чувствую, когда буду Redis для токенов прикручивать, снова буду перерабатывать структуру проекта и выделять в db пакет redis. Но это не точно... Доберусь, видно будет :)
А чего я вообще полез в бэкенд, можно почитать тут.