Testing
You can test your EVKafka consumers code using TestClient. The client
exposes an interface similar to producer's and allows to "send" events
to handlers directly from pytest tests.
Using TestClient
Consider having the application code in main.py:
from evkafka import EVKafkaApp
from pydantic import BaseModel
class Event(BaseModel):
key: str
app = EVKafkaApp(config={"topics": ["topic"]})
@app.event("Event")
async def handler(e: Event):
await store_event(e)
async def store_event(e: Event):
pass
store_event receives an expected event. Then we could
write our test using TestClient as following (assume pytest-mock is installed):
from evkafka import TestClient
from main import app, Event
def test_store_event(mocker):
mock_store_event = mocker.patch('main.store_event', new_callable=mocker.AsyncMock)
with TestClient(app) as client:
client.send_event(
topic='topic',
event={"key":"value"},
event_type='Event'
)
mock_store_event.assert_awaited_once_with(Event(key="value"))
TestClient works only with normal def fixtures and test functions, not async def.
You're still able to use AsyncMock and check whether mocked coroutines were awaited
as in the example above.
TestClient accepts events of following types: bytes, str, dict, pydantic model. Event is always
encoded into bytes and goes through consumer middleware stack before reaching target endpoint.
Multiple Consumers
A send_event is able to send an event to any registered consumer. If there is only one
consumer it is selected automatically. However, when there are few of them TestClient
needs to know what handlers you want it to communicate with. In this case you need to register
consumers with names:
# in main module
app.add_consumer(..., name='foo-consumer')
# in tests
def test_store_event():
with TestClient(app) as client:
client.send_event(
topic='topic',
event={"key":"value"},
event_type='Event',
consumer_name='foo-consumer',
)
Running Lifespan in tests
When used as a context manager TestClient calls an application lifespan automatically (if present).