Event driven design

Getting rid of the slow Masstransit test harness

I wrote a blog about replacing the timeout based test harness with a semaphore driven one here. This made things much more robust when you want blackbox type testing, fire a number of events and wait until all have been digested and their spawned child events are digested.

This worked well and robust. But it still used the Masstransit harness for hosting. This made the InMemory bus more than twice as slow as hosting Masstransit in a service, including database I/O so probably a lot slower when only looking at bus performance.

But it’s pretty easy hosting Masstransit from a none service project like a test project. Instead of configuring with AddMassTransitTestHarness use the standard AddMasstransit extension method. Now events will not be consumed when you publish them, this is because the IHostedService haven’t been started. So that’s an easy fix. If we base the code on the IHarness from my previous blog post.

public Harness(IEnumerable<IHostedService> services)
{
    _services = services;
}

public async Task Start()
{
    var source = new CancellationTokenSource();

    foreach (var service in _services)
        await service.StartAsync(source.Token);
}

public async Task Stop()
{
    var source = new CancellationTokenSource();

    foreach (var service in _services)
        await service.StopAsync(source.Token);
}

Call Start from your test setup and stop from your test teardown. This will start the background workers for Masstransit and make sure it listens and consumes events. The service will not work unless you add logging to your IoC config.

new ServiceCollection()
    .AddLogging();

Coupled with the harness-code from previous blog post you now have a very robust and fast test harness. Full code below

(more…)

A better Masstransit Test harness

At my latest customer project I choose to use Masstransit for events and Sagas. Its been a bumpy ride with outboxes and such, but now we have a pretty stable foundation to build upon. One problem have been testing. I like black box testing of our domain. Something like this.

[TestClass]
public class When_doing_a_complete_booking : BusinessTest
{
    private Booking _result;
    private DateTime _date;
  
    [TestInitialize]
    public void Context()
    {
        Guid bookingKey = Guid.Empty;
        _date = DateTime.Now.AddDays(5);
  
        _result = Given(db => /* Setup here */)
            .When(() => new SearchQuery{ Date = _date, ...})
            .And(result =>
            {
                bookingKey = result.First().BookingKey;
                return new ReserveCommand { BookingKey = bookingKey, ... };
            })
            .And(() => new ConfirmCommand
            {
                BookingKey = bookingKey, 
                ...
            })
            .Then(db => db.Set<booking>().FirstOrDefaultAsync(b => b.BookingKey == bookingKey));
    }
  
    [TestMethod]
    public void It_should_book_correctly ()
    {
        Assert.IsNotNull(_result);
        Assert.IsTrue(...);
    }
}

Masstransit harness really doesn’t support black box type testing. Chris Patterson favors a more unit testing-oriented approach, were you fire events and your Tests assert that events were consumed. You can await consumption with the built in harness, but its timeout oriented which makes it slow and unstable.

(more…)

SignalR event aggregation with Blazor WASM

As you probably know by now I love event aggregation and being able to seamless forward server side events to clients. My library SignalR.EventAggregatorProxy have been around for a while now and it enables seamless event aggregation between server and client. The .NET core client library just got updated to .NET 5. And as it turns out it works without any effort in Blazor WASM.

(more…)

Client – server event aggregation with SignalR ASP.NET Core

Event aggregation is really a pattern i like, there is something elegant about firing events and subscribers can listen to them without knowing who fired them. This creates decoupled domains both in backends and frontends. Back in 2013, at my customer of that time we saw an increasing demand for pub / sub and immediate update. We fired events on the backend event bus and in the frontend we had SignalR Hubs that picked up the events and forwarded them to the clients. This caused duplicated and similar code both on the client and on the web server. I decided to create an abstraction layer between SignalR and the event aggregator. The result is a library called SignalR.EventAggregatorProxy

It has now been ported to support ASP.NET Core, this article will focus on the changes, for the orginal article go here.

(more…)

Client server event aggregation with Angular

I dont fancy Angular much, its slow and Knockout with its MVVM approach is much cleaner, and faster since computed and observables only mutate and change view state when they actually need to (That will change with Angular 2.0). Anyway, my current customer sports Angular and then you just have to form inline 😀 We needed immediate update and you know I love event aggregation and probably know that I have a library for it, you can read more about it here!

I created a little wrapper for the the vanilla javascript client, install it using nuget
Install-Package SignalR.EventAggregatorProxy.Client.Angular

Basically it works by extending the Angular $rootScope and adds a eventAggregator function to all scopes. The eventAggregator function resolves the scope and then creates a closure with two methods, subscribe and publish. You can now listen to a event like (Serverside or client side event).

$scope.eventAggregator().subscribe(MyApp.MyEvent, onEvent);

(more…)

Single Page Application with Sub-routing

One of my colleagues is working on a Single Page Application, he asked me for help on a solid design for routing and specifically about sub-routing. Sub-routing in a SPA is complex, as an example when you click a link in a list you want that item to be presented in a modal window. If you close the modal window and press back in the history you want it to show again, and if you press forward you want it to close. I choose to attack this problem with an Event Aggregation approach, where changes to the route resulted in a change event being fired to any listener. (more…)

Client – server event aggregation with SignalR

Event aggregation is really a pattern i like, there is something elegant about firing events and subscribers can listen to them without knowing who fired them. This creates decoupled domains both in backends and frontends. At my latest customer we saw an increasing demand for pub / sub and immediate update. We fired events on the backend event bus and in the frontend we had SignalR Hubs that picked up the events and forwarded them to the clients. This caused duplicated and similar code both on the client and on the web server. I decided to create an abstraction layer between SignalR and the event aggregator. The result is a library called SignalR.EventAggregatorProxy

(more…)