у тебя есть 2 варианта:
1. разбивать код на чистые функции и тестировать их, тогда если каждая функция проходит тест, то нет необходимости в интеграционных(функциональных) тестах, так как ты уверен и так, что все будет верно. Правильно написанные юнит тесты все независимы друг от друга и выполняются ассинхронно и занимают мало времени, даже когда их очень много.
2. проверять в интеграционных(функциональных) тестах ОДНО конечное ожидаемое поведениие, если твой код вызывает какие-то побочные вещи помимо возвращенного результата, то стоит выносить такие вещи в отдельные функции их их проверять отдельно, тогда ты будешь уверен, что все более менее верно, но в большинстве случае проще следовать первому пункту и тогда просто отпадает необходимость во втором пункте
Еще, мокай внешние сервисы и пиши тесты только для важных вещей при взаимодествии со сторонними библиотеками, всегда можно функцию(интерфейс) сделать для получения/отдачи данных куда-то и ее протестировать. Ты не сможешь предуагать, что придет из внешнего сервиса, поэтому проще тестировать свои функции обработчики, что будет когда приходят валидные данные (проверять наличие нужных полей и т.д.) и когда нет.
В твоем конкретном случае в create_player нужно проверять, что пользователь создан, а отправку сообщения нужно проверять в отдельном юнит тесте с переданным юзером как аргумент, собственно -> пункт 1