Testing & mocking¶
Lightbus provides utilities to make testing easier. These utilities allow you to:
- Ensure only specific events & RPCs were fired
- Access the sent messages
- Mock RPC responses
Mocking with events¶
from lightbus.utilities.testing import BusMocker
from bus import bus
def test_firing_event():
    with BusMocker(bus) as bus_mock:
        # Setup the mocker to expect the auth.user_created was fired.
        # An error will be raised if the tested code fires any other events
        bus_mock.mock_event_firing("auth.user_created")
        # Run the code to be tested
        bus.auth.user_created.fire(field="x")
        # Check the event was fired once
        bus_mock.assert_events_fired("auth.user_created", times=1)
        # Get the fired event message
        message = bus_mock.get_event_messages("auth.user_created")[0]
        assert message.kwargs == {"username": "sarahjane"}
Mocking with RPCs¶
from lightbus.utilities.testing import BusMocker
from bus import bus
def test_calling_rpc():
    with BusMocker(bus) as bus_mock:
        # Setup the mocker to expect the auth.user_created was fired.
        # An error will be raised if the tested code calls any other RPCs
        bus_mock.mock_rpc_call("auth.check_password", result=True)
        # Run the code to be tested
        bus.auth.check_password(username="sarahjane", password="secret")
        # Check the event was fired once
        bus_mock.assert_rpc_called("auth.check_password", times=1)
        # Get the fired RPC
        message = bus_mock.get_rpc_messages("auth.check_password")[0]
        assert message.kwargs == {"username": "sarahjane", "password": "secret"}
Allowing arbitrary events and RPCs¶
By default the mocker will raise an error if any event or RPC is fired or called which has 
not be setup using the mock_event_firing / mock_rpc_call methods.
You can disable this and therefore allow any events or RPCs to the fired/called by using 
BusMocker(bus, require_mocking=False).
For example, the following will result in no errors even though we have not setup any mocks:
from lightbus.utilities.testing import BusMocker
from bus import bus
def test_permissive_mocking():
    with BusMocker(bus, require_mocking=False) as bus_mock:
        # Neither will cause an error despite the lack of mocking setup.
        # This is because we have set require_mocking=False
        bus.auth.user_created.fire(field="x")
        bus.auth.check_password(username="sarahjane", password="secret")
The @bus_mocker decorator¶
You can also access the bus mocker using the @bus_mocker decorator. We can rewrite 
our earlier event example (above) as follows:
from lightbus.utilities.testing import bus_mocker
from bus import bus
@bus_mocker(bus)
def test_firing_event(bus_mock):
    # Setup the mocker to expect the auth.user_created was fired.
    # An error will be raised if the tested code fires any other events
    bus_mock.mock_event_firing("auth.user_created")
    # Run the code to be tested
    bus.auth.user_created.fire(field="x")
    # Check the event was fired once
    bus_mock.assert_events_fired("auth.user_created", times=1)
    # Get the fired event message
    message = bus_mock.get_event_messages("auth.user_created")[0]
    assert message.kwargs == {"username": "sarahjane"}
Testing in Django¶
You can use the mocker in your Django tests just as shown above. For example, we can access the mocker using the context manager:
from django.test import TestCase
from lightbus.utilities.testing import BusMocker
from bus import bus
class ExampleTestCase(TestCase):
    def test_something(self):
        with BusMocker(bus, require_mocking=False) as bus_mock:
            ...
Or we can use the @bus_mocker decorator:
from django.test import TestCase
from lightbus.utilities.testing import bus_mocker
from bus import bus
class ExampleTestCase(TestCase):
    @bus_mocker(bus)
    def test_something(self, bus_mock):
        ...