Forced blocking in node.js

firebus's picture

I've been trying to unnest some callbacks in a user registration validation routine. I keep failing because I fundamentally don't understand the relationship between callbacks and scope in Node.js yet (maybe in Javascript generally). So clearly I need to solve this nesting problem in order to actually know what I'm doing :)

The problem is that it's difficult to test - I have a number of validation functions chained together with callbacks and depending on how I screw up the non-nested code, validation fails in a variety of ways.

So I need some tests to speed up my brute force approach to figuring out how Node works. I decided to use tobi since everyauth (our auth module) uses tobi for its own internal tests, so I had some example code to cut and paste.

Many of the validation functions that need testing make database calls to ensure that certain fields are unique.

These database calls are asynchronous, so they all happen at the same time, which causes problems.

For example, here's a set of tests:

- create a user, assert success
- create a user with the same username, assert failure
- create a user with the same email address, assert failure

Each attempt to create a user runs through the validation functions. Each validation function checks for existing users in the database asynchronously. Because all the callbacks are running in parallel, it's possible for all 3 validators to pass before the first user is inserted in the database. There's a race condition.

In production, this race condition gets caught by unique indices in the database, so it's not a bug. But in order to test the validation functions, I need to enforce some blocking so that the first user creation can complete before the second tests fire.

setTimeout() is an easy kludgy way to do this. I'm keeping my eyes open for a better pattern. I haven't figured out how to mock the database yet - this might be easier to do with a mock database that already has the first user, so that no forced blocking is necessary.

Powered by Drupal - Design by Artinet - Amazon Affiliate