Как видишь Request придется тебе мокать целиком и полностью...
Не вижу, зачем? Это pure data, там нечего мокать. Если ты про canWithdraw, то это простой чистый метод, зачем его мокать? Всякие БД и прочие внешние сервисы мокают из-за сайд-эффектов и из-за того, что поднимать БД/внешний сервис для каждого теста — крайне медленно.
Но можно canWithdraw вынести в Request как Lazy-поле, и снова мокать ничего не надо.
Наш мир, в первую очередь, причинно-следственный, и поэтому императивная модель
Не применима, т.к. позволяет менять уже существующие причинно-следственные события, когда в реальном мире они не меняются, только порождаются новые. Чисто. Функционально.
Невозможно сварить борщ не составив последовательность действий. Даже если ты просто собираешь домик из готовых кубиков, ты не можешь начать строительство с крыши.
Эти аналогии вообще к чему? По-твоему функциональные программы пишут на лету, в рантайме? Программа и есть описание процесса, выполненное в той или иной нотации/модели.
Ну есть скажем требование: "в случае неудачного соединения N-раз повторить повторить попытку, после чего сообщить пользователю об ощибке". Вполне себе нормальный сценарий, который тоже можно протестировать.
Ну вот смотри, D_KEY, вместо того, чтобы декомпозировать код и вынести логику retry в отдельный RetriableConnection с настраиваемой политикой, отдельно и независимо протестированную, Fester решил накостылять сомнительные тесты прям над бизнес-логикой, сохранив её сложность и зафиксировав эту сложность в спецификации (тесте). Чё-т не очень ему TDD помогает делать код/архитектуру лучше.