How to run Typer-command (Tiangolo) in async test (pytest)?

98 Views Asked by At

I created a command createserviceuser in manage.py:

# manage.py

import asyncio
from functools import wraps
from typing import Any

import typer
import uvicorn
from app.config import settings
from IPython import embed
from typing_extensions import ParamSpec


typer_app = typer.Typer()


class UsernameNotSetError(Exception):
    pass


class PasswordNotSetError(Exception):
    pass


class UserNotFound(Exception):
    pass


class ServiceUserRepository:

    def __init__(self, session: AsyncSession):
        self._session = session

    async def create_user(self, data):
        """Creates service user.

        Raises:
            UsernameNotSetError
            PasswordNotSetError

        """

    async def check_user_created(self, username):
        """Checks user existance

        Raises:
            UserNotFound

        """


def coro(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return asyncio.run(func(*args, **kwargs))
    return wrapper


@typer_app.command()
@coro
async def createserviceuser(username: str, password: str, email: str = None):
    try:
        async with Session.begin() as session:
            resository = ServiceUserRepository(session)
            await resository.create_service_user(username, password, email)
    except UsernameNotSetError:
        print("Username not set")
        raise typer.exit
    except PasswordNotSetError:
        print("Password not set")
        raise typer.exit

    print("User created")


if __name__ == "__main__":
    typer_app()

Then I want to test it. But to test it in async test because I need to run async fetch method:

# conftest.py


def service_user_repository(session):
    return ServiceUserRepository(session)



# test_commands.py

from manage import typer_app

cli_runner = CliRunner()


class TestCreatedServiceUserCommand:

    async def test_username_not_set(self, service_user_repository):
        empty_username = ""
        result = cli_runner.invoke(typer_app, ["createserviceuser", empty_username, ""])
        # when async command in not being invoked, result.stdout is empty string
        assert "Username not set" in result.stdout

        with pytest.raises(UserNotFound):
            await service_user_repository.check_user_exists(empty_username)

The problem with this is that it seems that the Typer-command is not being invoked because result.stdout is an empty string. How to fix it?

0

There are 0 best solutions below