Writing testable private methods with Node.js modules

2b8729c02bc2fb886b32ed23cb7b0a31?s=47 qubyte
June 19, 2014

Writing testable private methods with Node.js modules

In this 5 minute lightning talk, I present a way to write private methods that are still trivially testable with Node.js modules.

2b8729c02bc2fb886b32ed23cb7b0a31?s=128

qubyte

June 19, 2014
Tweet

Transcript

  1. Writing testable private methods with Node.js modules Mark S. Everitt

    (@qubyte) June 19, 2014 @ Async
  2. Why test? • Assert behaviour. Publish with confidence. • Maintain

    behaviour. Refactor with confidence. • Add tests after bugfixes. Avoid regressions.
  3. Why use private methods? • Small API surface. Less for

    users to learn. • Protect internal implementation to allow refactoring.
  4. But... Writing private methods is a little tricky.

  5. Modules help us out! function AsyncAttendee(name) { this.name = name;

    } // Make the module a reference to the constructor. module.exports = AsyncAttendee; // "private" methods take context as the zeroth argument. function sayHello(asyncAttendee) { return 'Hello ' + asyncAttendee.name + '!'; } AsyncAttendee.prototype.hello = function () { console.log(sayHello(this)); };
  6. But... What about testing that private method?

  7. Option 1 function AsyncAttendee(name) { this.name = name; } //

    Make the module a reference to the constructor. module.exports = AsyncAttendee; // "private" methods are prefixed with _ . AsyncAttendee.prototype._sayHello = function () { return 'Hello ' + this.name + '!'; }; AsyncAttendee.prototype.hello = function () { console.log(this.sayHello()); };
  8. Option 1 Don’t do this.

  9. Option 1 Users won’t respect convention!

  10. Option 2 Use a module. • core vm module •

    sandboxed-module
  11. Option 2 Lots of magic going on.

  12. Option 3 AsyncAttendee.js

  13. Option 3 AsyncAttendee index.js

  14. Option 3 AsyncAttendee index.js private.js

  15. Option 3 // index.js var privateMethods = require('./private'); function AsyncAttendee(name)

    { this.name = name; } module.exports = AsyncAttendee; AsyncAttendee.prototype.hello = function () { console.log(privateMethods.sayHello(this)); }; // private.js exports.sayHello = function (asyncAttendee) { return 'Hello ' + asyncAttendee.name + '!'; };
  16. Option 3 Use a namespace module. • "Public" to the

    filesystem (and therefore tests). • "Private" to JS outside your module.
  17. Thank you for your attention! Pop Quiz: What does return

    do in a function called with new?