DEV Community

Why I struggle with Node

Graham Cox on January 03, 2017

I'll admit it, I actually quite like Node.js. Especially in the ES6/ES7 variety. It's not perfect, but what language is? But what it is is a very q...
Collapse
 
spion profile image
Gorgi Kosev

Some ideas that made my life easier:

Mocking modules: github.com/thlorenz/proxyquire

Build system: Use webpack, bash, npm scripts. Its more difficult under Windows, I know. But Grunt and Gulp have been so awful for me, that even installing bash under cygwin manually is better. Most npm scripts will work okay under windows too.

Compiler / Static checks: Swap Babel with TypeScript.

Code coverage with mocha and TypeScript:


tsc && 
  istanbul cover -x 'tests/**/*.js' --report none _mocha -- 'tests/**/*.js' && 
  remap-istanbul -i coverage/coverage.json -o coverage/html -t html

Enter fullscreen mode Exit fullscreen mode

The key here is remap-istanbul, which will give you more useful results when you have a compile-to-JS step. Make sure that sourceMap is true for typescript's configuration though.

Collapse
 
grahamcox82 profile image
Graham Cox

Mocking modules can be done in a number of ways, but almost all of them seem to work on the require calls. Using ES6 means that you use import statements instead - which Babel rewrites to require, but outside of your control. There is a module I found - babel-rewire-plugin - which allows you to replace variables - including imports - inside a module, but even that just feels clunky. Coming from a Java world, what I feel like I want is a Dependency Injection setup, where I inject modules into each other, rather than pulling them in using require. However, I know that this isn't the standard Node way of doing things, and I'd rather do things the "correct" way than try to reproduce the way I work in a different language just because it's what I know.

The Node Build Systems I've never had much problem with. It can be a pain getting Grunt or Gulp to do exactly what I want it to, and some of the modules have problems, but in general I can cope there.

Typescript I've not yet used. I've used Flow, and kept running into problems where even though I had typing information on all of my code I didn't have it on the libraries I depended on, which just made it clunky.

Collapse
 
spion profile image
Gorgi Kosev

Regarding DI, node modules are already basically a service locator, so you don't really need it. Definitely not for testing anyway.

Proxyquire does need some ES6/babel/typescript love, I agree, but its just a matter of looking at the compilation output of babel and setting up the mocks accordingly. Would be nice if there was direct support for it. Sounds like a good pull request or module :)

TS largely solves the 3rd party library problem of flow. The number of available type definitions is quite impressive: npmjs.com/~types

I second the recommendation for VSCode. Don't know if it solves all your debugging troubles though. A lot of the problems with mocha come from it not playing well with other tools unless you use the _mocha binary, since mocha itself likes to start _mocha as a subprocess IIRC

Thread Thread
 
grahamcox82 profile image
Graham Cox

The DI needs are a lot more than just Service Locator though. It is all about abstracting away the wiring of your modules. It means that you can change the service that a module depends on simply by changing the wiring, and not changing the module itself. And that instantly means that the modules have to depend on the API of the service, not the implementation.

Regarding Proxyquire or similar, that would work but it means doing the imports in the middle of your tests - which is, of course, how Node does these things. That goes against the idea from ES6 that imports are done before any code, and simply set up the scene for your code to work.

Collapse
 
rubberduck203 profile image
Chris McClellan

I'm not sure what issues you're having with debugging, but I've found debugging with VS Code to work really well.

Collapse
 
grahamcox82 profile image
Graham Cox

I've not tried VS Code yet to be honest. Most of the Node work I do is in Atom, and on the occasions I need to do debugging I use the node-debug module, which just runs the application with the Chrome developer tools open.

What I've not yet worked out how to do is to debug a single unit test, or to connect a debugger to an already running application, both of which can be very useful.

Collapse
 
rubberduck203 profile image
Chris McClellan

I think Code is using the new version of the debugger. Maybe the newer version of the debugger will help? If you do decide to give Code a shot, the "debugging with vs code" section here may help. I've had no issues debugging mocha unit tests. Sometimes I forget that it's not a "real" ide. christopherjmcclellan.wordpress.co...

Thread Thread
 
grahamcox82 profile image
Graham Cox

It's definitely on my list of things to try out. The problem is, it's not a small list :)

Thread Thread
 
rubberduck203 profile image
Chris McClellan

I feel you there. It took a month of weekends for me to come up with a stack I was reasonably happy with. I'm still unsure what would make me say "let's use Node for this one".

Collapse
 
flosalihovic profile image
Florian Salihovic

Webstorm works like a charm.

Collapse
 
eduardohitek profile image
Eduardo Hitek

Hi! since you mentioned Atom, I would to know which plugins do you use on it for working with Node.
Thanks in advance.

Thread Thread
 
grahamcox82 profile image
Graham Cox

Good question. I've actually moved away from Atom to VS Code these days, but my Atom Plugin list that make sense for Node related stuff is:

  • atom-import-sort
  • atom-lupa
  • babel-react-syntax
  • build-grunt
  • colorful-json
  • es6-javascript
  • js-hyperclick
  • language-babel
  • language-javascript-jsx
  • linter-eslint
  • linter-package-json-validator
  • npm-helper
  • npm-plus

There's plenty of other plugins that are useful as well, for things like Git and the Minimap, but they aren't Node specific.

Collapse
 
twipped profile image
Jocelyn Badgley

For setting up databases to run integration tests against I've had great success using mktmp.io and its node module. It's missing a few DBs (neo4j, most notably), but launch time is less than half a second and response time is more than adequate for integration testing purposes. You can see it in use here: github.com/ChiperSoft/mysequel/blo...

For handling external APIs in integration tests I've used nock-vcr-recorder successfully. The first time the test passes it records all the http requests performed and stores them in json files, which then get replayed on future test runs. This is super handy for running tests in CI boxes that don't have access to those services. It just can be a bit of a bear if you need to remake the recordings and the environment you created them against doesn't have the same state any more.

Finally, I highly recommend node-tap or AVA over mocha and sinon. The tests are more reliable because they don't rely on exception throwing for assertions. One of Mocha's largest flaws is that a test that performs no assertions is indistinguishable from a test that passed.

Collapse
 
grahamcox82 profile image
Graham Cox

mktmp.io looks fantastic, but it unfortunately fails one of the requirements for proper integration testing - running against local services. Having the temporary databases hosted on a cloud server means that the build cannot be run without internet access - such as from a train or plane. Certainly worth investigating though :)

nock-vcr-recorder also looks very useful, and I will certainly be adding that to my list of things to play with when I get time :)

Collapse
 
yhippa profile image
Richard Yhip

I used to shake my fists at Maven but once you don't have it anymore you suddenly realize what you're missing.

I feel almost exactly the way you do about node coming from Java EE-land. I haven't gone into the end-to-end aspects but integration testing looks cumbersome like you mentioned. Node seems so new and there are way more equally valid ways to do things. Grunt vs Gulp anyone?

That said, I do like how it seems like a platform that's built for the era of modern web applications. I eventually want to check out how microservices are done in Node.

Collapse
 
theothermattm profile image
Matt M.

Great post! I agree with a lot of what you said. You inspired me to write a related post after a chat with a friend of mine about a similar topic: code.theothermattm.com/where-to-st...

Collapse
 
stan1y profile image
Stanislav Yudin

Yep, everything you do in JavaEE suddenly make it way more complicated than necessary. And maven... sign... some habits you just have to overcome, like drugs.

Collapse
 
peteroreilp25 profile image
peter o'reilly

You should checkout bearcat.js for dependency injection. Apart from the infuriating stack trace suppression it's a pretty powerful DI tool which I've used on some projects.