Node.js "should" library assertion, how does it work? - node.js

Our Mocha test suite has this line:
model.getResourceDependencies.should.be.a.Function;
the test code uses the should library
as you can see the above expression is neither an assignment nor an invocation, or is it?
How does this work? Is there some sort of underlying mechanism onPropertyRead() or something like that so that the should library can execute something even if no function is explicitly called?
By the way, it's damn near impossible to remember any of the should or chai APIs.

should.js uses ES5 getter.
https://github.com/shouldjs/should.js/blob/9.0.2/lib/should.js#L105
chai uses it too.
https://github.com/chaijs/chai/blob/3.5.0/lib/chai/interface/should.js#L35
In general, such behavior is available with ES5 getter or ES6 Proxy (and Object.prototype.__noSuchMethod__
in old days)

Related

What is role of the suite function in Mocha?

I read the book Web Development with Node.js and Express. And there is used the function suite().
var assert = require('chai').assert;
suite('tests', function () {
// set of tests
});
I don't understand where it comes from. I can't find any documentation about this function.
Seems that it looks and has same functionality like the describe() function in Mocha.
Mocha supports several different ways of writing tests (interfaces) so that you can choose a style that suits your methodology. describe() and suite() essentially do the same thing: they let you label and group together a set of tests; the grouped tests are organised under a common label in the output and can use common setup and teardown functions.
The choice of which function to use depends on whether you are using a Behaviour Driven Development (BDD) methodology (where you describe() the behaviour you want it() to do), or Test Driven Development (TDD), where you define a suite() of test()s you want your code to pass. You should choose whichever style you feel makes your code more readable.
Here's a blog explaining the Difference Between TDD and BDD with regard to test design.
Documentation can be found on the mocha website: https://mochajs.org/#tdd
suite is the TDD version of describe. You generally use it to describe and isolate the functionality/features/behaviour that you are going to test.

Proxyquire, rewire, SandboxedModule, and Sinon: pros & cons

When mocking Node dependencies, I've happened upon the following libraries:
Proxyquire
Rewire
SandboxedModule
Sinon
They all seem to do more-or-less the same thing: allow you to mock require() calls (with the exception of Sinon which mocks pretty much everything). They all seem to require some pretty elaborate setup, noting the exact syntax of the string passed to require -- not great during refactoring.
What are the pros and cons of each library? When would I choose one over the other? What are example use-cases where each library excels? What are other products in this space that are better?
It totally feels like cheating, but since no one else is answering the question, here goes:
Proxyquire takes over require and lets you inject fakes anywhere in the dependency chain. For requires you don't take over and for methods you don't define for requires you do take over, it'll fall back to the original. This can be disabled with noCallThru. Thus it still loads the original, just replaces things with the things you define. Unlike Rewire and SandboxedModule, you can't define global variables for your require overloads.
Rewire takes over require and injects __get__ and __set__ properties into each module. If you know the private variable name, you can replace it. Think dependency injection.
SandboxedModule is nearly identical to Proxyquire except it runs the entire process in a new V8 vm. (There is a per-test performance cost to this approach.) It also has a nasty bug in v 1.0 that makes it fail when something you didn't replace references a native module it doesn't support. See https://github.com/robrich/sandboxed-module-graceful-fs.
Sinon doesn't take over require like the other 3. Rather, it's a more traditional mocking framework. Replace specified methods with fakes, or create a mock that tracks when it was called.

Why does TypeScript need Node.js?

This is probably not the best question but I'm still completely new to JS. I'm interested in Typescript (being an AS3 dev), but I keep reading that I need to instal node.js to compile it? why is that?
TypeScript is a language that compiles into JavaScript. The compiler that does this, appears to be written (or at least distributed) in JavaScript. And node.js is the most common way to execute JavaScript outside a browser.
The typescript compiler is simply JavaScript, which is executed by node.js to compile things.
Why is that, you ask? Well, because that's what the developers of the compiler chose to write their compiler in. It could have been any language they wanted really.
The compiler is actually written in TypeScript. Yeah, a compiler written in the language it's supposed to compile, which may seem strange. But how that works is beyond the scope of this question.

How to handle should.js assert error

How should one handle uncaught exception thrown by a should.js (or node.js) failed assertion and keep execution on the same function/block where the assertion failed?
I tried wrapping the assertion in a try/catch but it seems to go up to process.on('uncaughtexception') anyway.
Lastly, is it a good practice and performant to use assertions in your production code to validate object
properties?
Thanks!
As the documentation states, Node's assert is basically for unit testing. Therefore I wouldn't use it in production code. I prefer unit testing to make sure that assertions are true in several situations.
However, I think you are using assert in a wrong way here: If an assertion fails something is wrong. Your app is in some kind of unknown state.
If you have some kind of handling for invalid objects assert isn't the right tool: As far as I understand your usecase you don't really require an object to be valid, but want to do something different if it's not. That's a simple condition, not an assertion.
Hi #dublx I think there are perfectly valid use cases to use assertions in the production code. E.g. if you rely on an external API that you know to behave in a certain way. This API might change suddenly and break your code. If an assertion would detect that the API changed and you would get an automatic e-mail you then could fix it even before your customers will recognize the break.
That said I recommend assume.js which solves exactly your problem. Even the performance is splendid: One assertion eats just 17µs or 0.017ms.

Should I switch from Vows to Mocha?

I'm trying to decide whether to switch from Vows to Mocha for a large Node app.
I've enjoyed almost all of the Vows experience - but there is just something strange about the argument passing. I always have to scratch my head to remember how topics work, and that interferes with the basics of getting the tests written. It is particularly problematic on deeply nested asynchronous tests. Though I find that combining Vows with async.js can help a little.
So Mocha seems more flexible in its reporting. I like the freedom to choose the testing style & importantly it runs in the browser too, which will be very useful. But I'm worried that it still doesn't solve the readability problem for deeply nested asynchronous tests.
Does anyone have any practical advice - can Mocha make deeply nested tests readable? Am I missing something?
Mocha is ace. It provides a done callback, rather than waitsFor that jasmine provides. I cant speak about migration from vows but from jasmine it was straight forward. Inside you mocha test function you can use async if you want (or Seq etc.. if you want to be legacy) though if you required nested callbacks at that point its an integration test, which might make you think about the granularity of your tests.
OT: 100% test coverage rarely delivers any value.
Deeply nested tests are solved by using flow control in your unit test suite.
Vows does not allow this easily because the exports style requires creating flow control libraries that support this.
Either write a flow control library for vows or switch to mocha and re-use an existing flow control library.

Resources