airtai / faststream

FastStream is a powerful and easy-to-use Python framework for building asynchronous services interacting with event streams such as Apache Kafka, RabbitMQ, NATS and Redis.
https://faststream.airt.ai/latest/
Apache License 2.0
2.12k stars 99 forks source link

Bug: starting the broker breaks in-memory behaviour #1479

Open Klavionik opened 1 month ago

Klavionik commented 1 month ago

Describe the bug I'm not really sure if this is a bug or not. If it's not a bug but an intended behaviour, then I suppose it should be at least mentioned in the docs.

Right now, if you start the broker and then try to patch it with the in-memory broker for testing purposes, call count assertions will fail (at least when testing a publisher).

It may seem obvious to someone, but I've spent quite some time trying to figure out the problem. Connecting a broker before running tests didn't seem like the problem: what if I wish to run tests both in-memory and with a real thing, so why not making a connection beforehand?

How to reproduce Consider this example code:

from collections.abc import AsyncIterator

import pytest
from dishka import Provider, provide, Scope, AsyncContainer, make_async_container
from faststream.rabbit import TestRabbitBroker, RabbitBroker
from faststream.rabbit.publisher.asyncapi import AsyncAPIPublisher

class RabbitProvider(Provider):
    @provide(scope=Scope.APP)
    async def broker(self) -> AsyncIterator[RabbitBroker]:
        dsn = "amqp://guest:guest@0.0.0.0:5672/"
        broker = RabbitBroker(url=dsn)

        await broker.start()
        yield broker
        await broker.close()

    @provide(scope=Scope.APP)
    async def publisher(self, broker: RabbitBroker) -> AsyncAPIPublisher:
        return broker.publisher()

@pytest.fixture
async def container() -> AsyncIterator[AsyncContainer]:
    container = make_async_container(RabbitProvider())
    yield container
    await container.close()

async def test_publisher(container: AsyncContainer):
    broker = await container.get(RabbitBroker)
    publisher = await container.get(AsyncAPIPublisher)

    async with TestRabbitBroker(broker):
        for i in range(10):
            await publisher.publish(f"message {i}")

        assert publisher.mock.call_count == 10

Running this test would lead to AssertionError: assert 0 == 10. However, if you remove await broker.start() call from the broker provider method, it works fine.

Expected behavior In-memory broker works even if the broker has established the connection.

Observed behavior In-memory broker doesn't register publish calls if it has established the connection before patching.

Environment Running FastStream 0.5.7 with CPython 3.12.0 on Darwin

Lancetnik commented 1 month ago

I am planning a big TestClient refactor, but now we should complete all production usecases to move forward, sorry, I add it to backlog (and big thanks for the report)

Btw, why are you not in the RU telegram group yet?

Klavionik commented 1 month ago

No worries, I don't expect every issue to be fixed in hours. :)

Btw, why are you not in the RU telegram group yet?

I enjoy reporting issues.