Doing BDD with SignalR and Jasmine

SignalR is one of the latest (and sexiest) elements in the .NET stack. Expect to hear more about SignalR if you haven’t already, because it delivers on the promise of push technology without the requirement of a fat client. If you’ve not yet read much about SignalR, clone the source code from GitHub or read Scott Hanselman’s post on SignalR for an introduction. The scope and inner-workings of SignalR are somewhat out of scope here, so I’ll just assume you’ve at least heard somethingabout SignalR and that you’re interested in it but have a few questions. I mean, if you’re into BDD/TDD, you should definitely be wondering:

So how testable is SignalR? If the magic of it is based in some form of maintained connection, the implication of how one has to code asynchronously against it makes testing p-r-e-t-t-y difficult. Testing in JavaScript is pretty difficult to begin with, so now what?

There’s this amazing TDD/BDD micro-framework called Jasmine that lends itself extremely well to all sorts of different JavaScript problem domains. I learned about Jasmine from some colleagues in the Ruby community, then found some pretty awesome resources on Jasmine, and have been waiting for an opportunity to try it out. This seemed like a perfect opportunity, so I dove in.

The Calculator SignalR Hub

This example will offer a solution to the simple problem of providing basic numeric calculations. Obviously, the first operation most users will need is some addition functionality.

image

The implementation of this method might look a little strange if you’re new to SignalR. It’ll make sense in just a moment when you see the corresponding JavaScript code. Think about it this way; the Clients property of any Hub is dynamic object that will represent a corresponding JavaScript method on each of the clients connected to the Hub.

image

The controller action for the client has no special glue or magic in it. It’s basically a shell to adhere to the requirement of having an action for the views.

image

On the client, there will be a few script references to make sure SignalR works properly.

image

This is the part where the dynamic client thing should make sense. The JavaScript code below demonstrates how to call this dirt-simple SignalR Hub and to generate some action on the client.

image

The call earlier, within the implementation of the Hub, is basically a way of the server telling the client, would you please run this method and pass it this data?It isn’t a really sexy example when you see it execute, of course, but it drives the point home. SignalR makes push ridiculously simple.

image

Bring on the BDD!

As if SignalR isn’t nifty enough, Jasmine gives us the ability to set up specifications and unit tests to make sure things are working properly and to guide development. Now, we get to put them together to answer the problem of how to test the client.(I’m not knocking other methods, like WaTiN or other automated testing implementations, here, this is just another way of skinning the same kitty.)

We’ll need to include the basic script references and CSS file to make Jasmine light up. You can download those from the Jasmine site, or they’re included in the GitHub repository I’ve created for the purpose of my continued tinkering in SignalR.

image

Once the Jasmine files are in place, it doesn’t hurt to create a pulse-check specification to make sure the glue’s dry. The JavaScript object shell below will be a roadmap for how we’ll solve this problem.

image

Once the specifications have been written up, Jasmine’s environment is created and the tests are executed.

image

If you’ve pinned the tail on the donkey to this point, the results should be quite self-explanatory when you view the calculator page again. If you don’t see the tests, check the passedcheckbox and the passing test will appear.

image

At this point, to test that the SignalR CalculatorHub is communicating with the client properly all that’s reallyneeded is a way to call the Addmethod from in a unit test and to verify that the JavaScript code’s showSummethod executed with a parameter of 4.

The first step in getting this working is to modify the test fixture class so it can be supplied any dependencies it might have. In this case, we plan on testing the calculator hub, so it’ll be passed into the fixture in it’s constructor. Also added is the addCallbackfield. At this point it’ll be set to false,but the plan is, to set this variable to the callback method that will be called when the calculation is completed by the hub.

image

Since the constructor’s changed it’d be wise to change the calling code, our jQuery readymethod. This time, we’ll go ahead and create an instance of the SignalR CalculatorHuband it’ll be provided as a construction argument.

image

Next, a new specification is added to the initmethod. This specification is the unit test that will demonstrate the calculator’s being called properly from the client JavaScript.

image

It’d help at this point to take a peek at the Jasmine Wiki article on Spies to get an idea of how this sort of verification can be accomplished. Jasmine’s Fluent syntax makes it pretty self-explanatory (and including vsdoc files to provide Intellisense in Visual Studio brings in the Jasmine methods). Jasmine, like Moq and other mocking frameworks, offers unit tests the capability of checking to see if methods have been executed properly.

image

If your Jasmine tests are executed at this point, you’ll see some p-r-e-t-t-y interesting results. For about 5 seconds the browser will let you know something’s happening by making the current test’s background color yellow.

image

Then the test will complete execution and fail. Jasmine is assuming via those calls earlier assume they should wait for an asynchronous response and if it doesn’t arrive, the tests will fail. They fail because the callback methods are never executed, and the tests expect them to be.

image

That addCallbackfield that was added to the test fixture is how this can be accomplished. The client’s showSummethod is the one thing that’s been omitted from the JavaScript code. That’s the method that the SignalR hub will try to call on each client whenever it needs to do so.

image

Within the test fixture resides the onAddmethod. It just executes the fixture’s addCallbackmethod and feeds it the results from the SignalR CalculatorHubcall.

image

Once that’s all wired up, the test should pass!

image

If you’re obsessive about verifying, just change the expected value to be something wrong and re-run the test. Obviously, if the math fails, so should the test. Otherwise it’d be a pretty useless calculator!

image

Recap

SignalR and Jasmine work quite nicely together. If you apply a little OO elbow grease and take the time to wire things up with callbacks and to verify the execution of those callbacks, SignalR can be tested rather effectively. All it takes is to properly stage, and then verify, that the Hub’s method is called and that, when the Hub fires the client callback, that the callback is executed as your code expects it to be executed.

Thanks for taking the time to stop by. Happy Coding!