Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NatsBroker.new_inbox() #1543

Merged
merged 8 commits into from
Jun 21, 2024
2 changes: 1 addition & 1 deletion docs/docs/en/getting-started/contributing/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pytest -m 'all'
If you don't have a local broker instance running, you can run tests without those dependencies:

```bash
pytest -m 'not rabbit and not kafka and not nats and not redis'
pytest -m 'not rabbit and not kafka and not nats and not redis and not confluent'
```

To run tests based on RabbitMQ, Kafka, or other dependencies, the following dependencies are needed to be started as docker containers:
Expand Down
13 changes: 13 additions & 0 deletions faststream/nats/broker/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,3 +901,16 @@ async def wrapper() -> None:
self.__is_connected = True

return wrapper

async def new_inbox(self) -> str:
"""Return a unique inbox that can be used for NATS requests or subscriptions.

The inbox prefix can be customised by passing `inbox_prefix` when creating your `NatsBroker`.

This method calls `nats.aio.client.Client.new_inbox` [1] under the hood.

[1] https://nats-io.github.io/nats.py/modules.html#nats.aio.client.Client.new_inbox
"""
assert self._connection # nosec B101

return self._connection.new_inbox()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add assert here to check, that the broker is already connected (and ignore this asset by noseq)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the hint. I only saw this comment after I added a check which raises a RuntimeError. Please let me know if you'd like me to use a regular assert statement instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use assert in this case. I prefer to use switchable checks for development.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, done. Out of curiosity, what do you mean by using "switchable checks for development"?

23 changes: 23 additions & 0 deletions tests/brokers/nats/test_new_inbox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from unittest.mock import patch

import pytest
from nats.aio.client import Client as NatsClient

from faststream.nats import NatsBroker
from tests.tools import spy_decorator


@pytest.mark.asyncio()
@pytest.mark.nats()
async def test_new_inbox():
with patch.object(
NatsClient,
"new_inbox",
spy_decorator(NatsClient.new_inbox),
) as m:
broker = NatsBroker(inbox_prefix="_FOO_TEST_INBOX")
await broker.connect()
inbox_name = await broker.new_inbox()

m.mock.assert_called_once()
assert inbox_name.startswith("_FOO_TEST_INBOX.")
1 change: 0 additions & 1 deletion tests/brokers/nats/test_test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ async def test_inbox_prefix_with_real(
assert br._connection._inbox_prefix == b"test"
assert "test" in str(br._connection.new_inbox())


async def test_respect_middleware(self, queue):
routes = []

Expand Down
14 changes: 11 additions & 3 deletions tests/tools.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import inspect
from typing import Any, Iterable
from unittest.mock import MagicMock


def spy_decorator(method):
mock = MagicMock()

async def wrapper(*args, **kwargs):
mock(*args, **kwargs)
return await method(*args, **kwargs)
if inspect.iscoroutinefunction(method):

async def wrapper(*args, **kwargs):
mock(*args, **kwargs)
return await method(*args, **kwargs)
else:

def wrapper(*args, **kwargs):
mock(*args, **kwargs)
return method(*args, **kwargs)

wrapper.mock = mock
return wrapper
Expand Down
Loading