Skip to content

Commit

Permalink
fix: before replace IoC
Browse files Browse the repository at this point in the history
  • Loading branch information
edpyt committed May 4, 2024
1 parent 0b07b92 commit 24987d4
Show file tree
Hide file tree
Showing 18 changed files with 121 additions and 68 deletions.
19 changes: 18 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ optional = true
pytest = "^8.0.2"
pytest-asyncio = "^0.23.5"
testcontainers = "4.4.0"
pytest-mock = "^3.14.0"

[tool.poetry.group.dev]
optional = true
Expand Down
3 changes: 0 additions & 3 deletions src/api/di/__init__.py

This file was deleted.

11 changes: 0 additions & 11 deletions src/api/di/config.py

This file was deleted.

7 changes: 0 additions & 7 deletions src/api/di/main.py

This file was deleted.

15 changes: 13 additions & 2 deletions src/api/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from blacksheep import Application
from nats import NATS

from src.api.auth.handler import BuberDinnerAuthHandler
from src.api.docs import setup_docs
Expand All @@ -10,10 +11,12 @@
def build_api() -> Application:
"""Build BlackSheep application"""

di_container = build_application_container()
app = Application(services=di_container, show_error_details=True)
app = Application(show_error_details=True)
setup_app(app)

app.on_start += setup_di
app.on_stop += close_connections

return app


Expand All @@ -27,3 +30,11 @@ def setup_app(app: Application) -> None:

app.use_authentication().add(BuberDinnerAuthHandler())
app.use_authorization()


async def setup_di(app: Application) -> None:
await build_application_container(app.services)


async def close_connections(app: Application) -> None:
await app.services.resolve(NATS).close()
14 changes: 11 additions & 3 deletions src/infrastructure/config/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@
class BrokerConfig:
host: str = "localhost"
port: int = 4222
login: str = "admin"
password: str = "admin"
login: str | None = None
password: str | None = None

@property
def full_url(self) -> str:
return f"nats://{self.login}:{self.password}@{self.host}:{self.port}"
conn_url = "nats://"

if self.login:
conn_url += self.login
if self.password:
conn_url += self.password

conn_url += f"@{self.host}:{self.port}"
return conn_url
6 changes: 3 additions & 3 deletions src/infrastructure/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@


class Config(BaseModel):
jwt_config: JWTConfig
db_config: DBConfig
broker_config: BrokerConfig
jwt_config: JWTConfig = JWTConfig(jwt_secret="secret", expiry_minutes=99) # noqa: S106
db_config: DBConfig = DBConfig()
broker_config: BrokerConfig = BrokerConfig()


def create_config_obj() -> Config:
Expand Down
9 changes: 5 additions & 4 deletions src/infrastructure/di/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@


@lru_cache
def build_application_container() -> Container:
container: Container = Container()
async def build_application_container(container: Container | None = None) -> Container:
if container is None:
container = Container()

container.add_instance(logging.getLogger(__name__), logging.Logger)
container.add_instance(setup_retort())

setup_config_di(container)
config = setup_config_di(container)
setup_extra_di(container)
setup_mapper_di(container)
setup_mediatr_di(container)
setup_message_queue_di(container)
await setup_message_queue_di(container, config)
setup_persistence_di(container)

return container
7 changes: 5 additions & 2 deletions src/infrastructure/di/message_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
from rodi import Container

from src.application.common.events.event_bus import EventBus
from src.infrastructure.config.config import Config
from src.infrastructure.event_bus.event_bus import EventBusImpl
from src.infrastructure.message_broker.interface import MessageBroker
from src.infrastructure.message_broker.main import make_broker_connection
from src.infrastructure.message_broker.message_broker import MessageBrokerImpl


def setup_message_queue_di(container: Container) -> None:
async def setup_message_queue_di(container: Container, config: Config) -> None:
nats_conn = await make_broker_connection(conn_url=config.broker_config.full_url)

setup_events_di(container)

container.add_singleton_by_factory(make_broker_connection, NATS)
container.add_instance(nats_conn, NATS)
container.add_transient(MessageBroker, MessageBrokerImpl)


Expand Down
10 changes: 2 additions & 8 deletions src/infrastructure/message_broker/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
from typing import AsyncGenerator

import nats

from src.infrastructure.config.broker import BrokerConfig


async def make_broker_connection(config: BrokerConfig) -> AsyncGenerator[nats.NATS, None]:
conn = await nats.connect(config.full_url)
yield conn
await conn.close()
async def make_broker_connection(conn_url: str) -> nats.NATS:
return await nats.connect(conn_url)
1 change: 1 addition & 0 deletions src/infrastructure/message_broker/message_broker.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import orjson
from nats import NATS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async def saving_changes(


async def publish_domain_events(entity: object, context: QueryContext) -> None:
mediator = build_application_container().resolve(Mediator)
mediator = (await build_application_container()).resolve(Mediator)

# Get hold of domain events
events = entity.events # type: ignore [attr-defined]
Expand Down
27 changes: 23 additions & 4 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,42 @@

import pytest
from blacksheep import Application
from pytest_mock import MockerFixture
from src.api.main import build_api
from src.infrastructure.config.broker import BrokerConfig
from src.infrastructure.config.config import Config
from src.infrastructure.config.db import DBConfig
from src.infrastructure.config.jwt import JWTConfig

from tests.integration.di import DIOverride, setup_test_di


@pytest.fixture(name="jwt_config", scope="session")
def create_jwt_config() -> JWTConfig:
return JWTConfig(jwt_secret="test-secret", expiry_minutes=9999)


@pytest.fixture(name="config", scope="session", autouse=True)
def create_config(
session_mocker: MockerFixture,
jwt_config: JWTConfig,
db_config: DBConfig,
broker_config: BrokerConfig,
) -> Config:
config = Config(
jwt_config=jwt_config,
db_config=db_config,
broker_config=broker_config,
)

session_mocker.patch("src.infrastructure.config.config.create_config_obj", return_value=config)
session_mocker.patch("src.infrastructure.di.config.create_config_obj", return_value=config)

return config


@pytest.fixture(name="app", scope="session")
async def create_app(jwt_config: JWTConfig) -> AsyncGenerator[Application, None]:
app: Application = build_api()

setup_test_di(app, DIOverride(jwt_config))

await app.start()
yield app
await app.stop()
26 changes: 14 additions & 12 deletions tests/integration/fixtures/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .db.sqla import create_async_sa_session, create_sa_session_factory, create_test_sa_engine
from .events import (
connect_nats,
create_broker_config,
create_event_bus,
create_nats_container,
create_nats_message_broker,
Expand All @@ -12,22 +13,23 @@
from .repositories import create_menu_repository, create_user_factory, create_user_repository

__all__ = (
"create_db_config",
"create_postgres_db",
"connect_nats",
"create_alembic_config",
"run_db_migrations",
"create_async_sa_session",
"create_sa_session_factory",
"create_test_sa_engine",
"create_auth_token",
"di_overrides",
"test_client",
"create_menu_repository",
"create_user_repository",
"create_user_factory",
"create_broker_config",
"create_db_config",
"create_event_bus",
"create_menu_repository",
"create_nats_container",
"menu_create_handler",
"create_nats_message_broker",
"connect_nats",
"create_postgres_db",
"create_sa_session_factory",
"create_test_sa_engine",
"create_user_factory",
"create_user_repository",
"di_overrides",
"menu_create_handler",
"run_db_migrations",
"test_client",
)
11 changes: 9 additions & 2 deletions tests/integration/fixtures/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
from blacksheep.testing import TestClient
from src.application.persistence.menu_repo import MenuRepository
from src.application.persistence.user_repo import UserRepository
from src.infrastructure.config.jwt import JWTConfig

from tests.integration.di import DIOverride, setup_test_di


@pytest.fixture
def di_overrides(user_repo: UserRepository, menu_repo: MenuRepository) -> list[DIOverride]:
return [DIOverride(user_repo, UserRepository), DIOverride(menu_repo, MenuRepository)]
def di_overrides(
jwt_config: JWTConfig, user_repo: UserRepository, menu_repo: MenuRepository,
) -> list[DIOverride]:
return [
DIOverride(jwt_config),
DIOverride(user_repo, UserRepository),
DIOverride(menu_repo, MenuRepository),
]


@pytest.fixture
Expand Down
17 changes: 14 additions & 3 deletions tests/integration/fixtures/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import pytest
from src.application.common.events.event_bus import EventBus
from src.application.dinners.events.menu_create_handler import MenuCreateHandler
from src.infrastructure.config.broker import BrokerConfig
from src.infrastructure.event_bus.event_bus import EventBusImpl
from src.infrastructure.message_broker.interface import MessageBroker
from src.infrastructure.message_broker.main import make_broker_connection
from src.infrastructure.message_broker.message_broker import MessageBrokerImpl
from testcontainers.nats import NatsContainer

Expand All @@ -16,12 +18,21 @@ async def create_nats_container() -> Generator[NatsContainer, None, None]:
yield nats_container


@pytest.fixture(name="broker_config", scope="session")
def create_broker_config(nats_container: NatsContainer) -> BrokerConfig:
host, port = nats_container.nats_host_and_port()
return BrokerConfig(host=host, port=port)


@pytest.fixture(name="nats_conn")
async def connect_nats(nats_container: NatsContainer) -> AsyncGenerator[nats.NATS, None]:
conn_url = nats_container.nats_uri()
nats_conn = await nats.connect(conn_url)
yield nats_conn
await nats_conn.close()

conn = await make_broker_connection(conn_url=conn_url)

yield conn

await conn.close()


@pytest.fixture(name="message_broker")
Expand Down
3 changes: 1 addition & 2 deletions tests/integration/menu/test_repository.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import pytest

from src.application.menu.dto.average_rating import AverageRatingDTO
from src.application.persistence.menu_repo import MenuRepository
from src.domain.host.vo.host_id import HostId
Expand All @@ -12,7 +12,6 @@ async def test_get_all_menu(menu_repo: MenuRepository) -> None:
assert resp == []


@pytest.mark.skip("Error with IoC container. https://github.com/edpyt/buber_dinner/issues/14")
async def test_add_menu(menu_repo: MenuRepository) -> None:
menu = Menu.create(
name="test",
Expand Down

0 comments on commit 24987d4

Please sign in to comment.