Skip to content

How to test code that uses the bus to do things

Mogens Heller Grabe edited this page Jun 21, 2019 · 9 revisions

When your code depends on IBus and uses it to send messages, you can sometimes get away with using dynamically created mocks (e.g. by using something like FakeItEasy).

Other times, you have more stuff going on, which would be too tedious to test using generic mocking libraries. Therefore, Rebus' test helpers come with FakeBus, which is an implementation of IBus that simply records all the stuff you do to it.

To get started with it, install the Rebus.TestHelpers package via NuGet, and then you simply do something like this:

// create the fake bus
var bus = new FakeBus();

// exercise your logic
new SomeKindOfSut(bus).DoStuff();

// assert that your SUT did what it should have done
var events = bus.Events; // IEnumerable of things that happened

An example could be an implementation of the IInvitationService that was mentioned on the How to unit test a message handler page:

public interface IInvitationService
{
    Task Invite(string emailAddress, DateTimeOffset invitationTime);
    Task ResendInvite(string emailAddress);
}

We now pretend that our implementation of IInvitationService is DefaultInvitationService, and we want to test its behavior when we call Invite on it. It uses the bus to send an email to the provided email address, so that's what we're going to check.

The logic looks like this:

class DefaultInvitationService : IInvitationService
{
    readonly IEmailTemplateService _emailTemplateService;
    readonly IBus _bus;

    public DefaultInvitationService(IBus bus, IEmailTemplateService emailTemplateService)
    {
        _bus = bus;
        _emailTemplateService = emailTemplateService;
    }

    public async Task Invite(string emailAddress, DateTimeOffset invitationTime)
    {
        var (subject, body) = _emailTemplateService
            .GetInvitationTemplate(
                emailAddress: emailAddress,
                invitationTime: invitationTime
            );

        await _bus.Send(new SendEmail(
            to: emailAddress,
            subject: subject,
            body: body
        ));
    }

    public async Task ResendInvite(string emailAddress)
    {
    	// ignore for now
    }
}
Clone this wiki locally