Testing with javascript

I don’t know about you, but I found the transition from .NET and ruby over to JavaScript rather painful. There’s quite a few quirks along the way, but one of the hardest ones for me is the asyncronous nature of the code. Martin Fowler has put up a great post that explains all this in much more detail and with bigger words than I ever could.

So today I was creating a new unit test for a greenfield project (something we do every month at manchester codejo, you should come along!) to ensure that when I queried my API, I got the expected information out of the database.

I want to get back all the services for a particular customer, as I know that Mongo sends me an array of objects back, I’ll start with an assertion that the customer id of the first object is the one I searched for.

In pseudo-code, ruby or .net stylee, this would look like:

customer_id = 123;
services_repo.add({customer_id=>customer_id})

services_query = ServicesQuery.new()
services = services_query.by_customer(customer_id)
assert_equal(services[0].customer_id, customer_id)

Now, this is how I thought it would look in javascript:

test('check only get the services for that customer',function(done){
serviceRepository.add({
customer_id: "12536"
});

var id = '12536';

allegroNetworksManagementQuery.services(id, function(serviceList){
assert.equal(serviceList.services[0].customer_id, id);
done();
});
});


dev@bob:~$ mocha ./tests/unit --ui qunit --recursive --reporter nyan

So the test went red, I made it go green, I committed, refactored, committed… and CI went red. That’s a bit weird, runs ok on my machine. After a confused number of re-runs I concluded this was an intermittent red, indicating a race condition. This is where you remember that Javascript runs the code asyncronously, hence the little done variable.

This is where I got stuck. Clearly there was a race condition with my setup of injecting the expected data into the database, but how do I ensure this was done first? I must admit it all got a bit too confusing for me. After several brews, going round in circles in my head, frantic googling and a walk, I remembered all the tests we’d written using Zombie, when Iain and Ben still worked here.

We also use mocha, but with a different test format. For that we use the bdd interface rather than qunit, which allows us to use the following format:


describe('Array', function(){
before(function(){
// ...
});

describe('#indexOf()', function(){
it('should return -1 when not present', function(){
[1,2,3].indexOf(4).should.equal(-1);
});
});
});

The interesting bit here is the before function on line two. We use this as a setup and the describe ensures that the before runs prior to the tests inside the it method.

Using this format, I rewrote my test:


describe("Get the services for a customer", function() {
var id = '12536';

before(function(done) {
serviceRepository.add({
customer_id: id
});
done();
});

it('service customer id is the one I serach for,', function(done) {
allegroNetworksManagementQuery.services(id, function(serviceList){
assert.equal(serviceList.services[0].customer_id, id);
done();
});
});
});


dev@bob:~$ mocha ./tests/unit --ui bdd --recursive --reporter nyan

Job’s a good un.