Test nodejs server code without running server - node.js

New to nodejs testing.
I have a nodejs server that runs some complex server side logic, and I'm looking at building a unit test runner for that code. I do not want to run the server and tests sending it requests though, as that doesn't expose all the modules and functions I want to test on the server side. That will be more like integration testing. I just want to import those server side files, which are written as AMD modules, and call their functions one by one in unit tests.
What's the best way to go about doing this?

You will want to start by installing a unit-test and assertion framework to your current project. Then you will also want to add requirejs (r.js).
We are currently using mochajs for unit-testing with should as the assertion library. Both have great adoption and feature support for testing Node.js.
npm install mochajs shouldjs requirejs --save-dev
This will add three packages to your local node_modules as well as save them inside your package.json's devDependencies.
Go ahead and setup a unit test directory in your project and create a new test file, [your_module_name]_test.js:
const should = require('should'),
foo = require('foo');
describe('foo', () => {
it('returns the letter a', () => {
foo().should.eql('a');
});
});
In the test file you will want to require the module under test and then unit-test as usual.
You can then run the test through r.js
./node_modules/requirejs/bin/r.js [your_test_dir]/[your_module_name]_test.js
You can also install mochajs globally and then simply run the mocha command instead of using the bin inside of your local node_modules.
Best of luck, and hope this helps.

Related

Loading Nodejs Module at runtime in electron app

Currently I am playing around with electron using vue-cli-plugin-electron-builder along side a simple vue project. This is the project https://github.com/nklayman/vue-cli-plugin-electron-builder .
vue create my-project
cd my-project
vue add electron-builder
npm run electron:serve
My goal is to add a simple plugin-like architecture. The app serves only base functionality but can be extended with "plugins". Those plugins therefore are not included in the built, but will be loaded at runtime by electron. I would prefere when those plugins just behave like node modules ( module.exports = ) with its own dependencies ( probably with a package.json file inside ). I would locate those plugins at app.getPath('userData') + '/Plugins.
I looked at a few approaches on how to tackle this problem :
1. Using Nodejs vm module
First, I tried using Nodejs vm module to read and execute a script from an external file, all at runtime. It works great so far, although I would not be able to use external dependencies inside those loaded scripts. If I want to use external dependencies inside the plugin scripts, those dependencies must have been included in the electron build beforehand. Somehow defeats the whole purpose of having plugins ... only vanilla js + nodejs base modules would be possible .
2. using global.require
I saw this solution in another SO answer.
Using node require with Electron and Webpack
Webpack/electron require dynamic module
They say to use global.require but it throws an error saying global.require is not a function. The solution looked promising first, but somehow I can't get it to work.
3. simply use require
Of course I had to try it. When I try to require an external module from a non-project location it won't find the module, even if the path is correct. Again, the path I am trying to locate the module should be at app.getPath("userData"), not in the projects root directory. When however, I locate the plugins inside the root directory of the project it gets included in the built. This again defeats the purpose of having plugins.
Goal
So far, I haven't found a viable solution to this. I simply want my electron app to be extendible with basic node modules at runtime ( following a pre-defined schema to simplify ) . Of course there is atom, made with electron, using their own apm manager to install and load plugins, but this seems way to overpowered. Its enough for me to only have plugin files located locally, to have a public "marketplace" is no goal. Also, it's ok if the app has to reload / restart to load plugins.
Any ideas ?
After more and more research I stumbled over 2 packages :
https://www.npmjs.com/package/live-plugin-manager
https://github.com/getstation/electron-package-manager
both integrating npm to programmatically handle package installation at runtime. I settled for live-plugin-manager for now since its better documented and even allow package installation from local file system.
Pro
I was able to integrate the system out-of-the-box into a vanilla electron app. Works like a charm.
Cons
.I was not able to use it inside a vue electron boilerplate (like the one I said I was using in OP), since webpack is interferring with the require environment. But there sure is a solution to this.
Update : I was able to get it to work eventually inside a webpack bundled electron vue boilerplate. I accidentally mixed import and require . The following code works for me using live-plugin-manager
// plugin-loader.js
const path = require('path');
const { PluginManager } = require('live-plugin-manager');
const pluginInstallFolder = path.resolve(app.getPath('userData'), '.plugins');
const pluginManager = new PluginManager();
module.exports = async (pkg) => {
// installs pkg from npm
await pluginManager.install(pkg);
const package = pluginManager.require(pkg);
return package
}
// main.js
const pluginLoader = require('./plugin-loader');
pluginLoader("moment").then((moment) => {
console.log(moment().format());
})
This will install "moment" package from npm during runtime into a local directory and load it into the app, without bundling it into the executable files.

How do I use harmony_async_iteration with jest?

I would like to test code in a node project that uses async iteration without using babel.
Based on https://github.com/facebook/jest/issues/2485, I tried running jest using node --harmony_async_iteration ./node_modules/.bin/jest. However, I still see syntax errors in my module where async iteration syntax is used. The node command line option was ineffective, as if jest spawned a new process for the test runner, without using --harmony_async_iteration.
My async iteration source file is parsed without error when loaded by node (without jest) using --harmony_async_iteration.
Babel is an integral part of jest. It is not necessary to use babel to transpile your application for non-test use, but babel absolutely must be configured in order to allow async generators to work with jest.
Install the babel-plugin-transform-async-generator-functions:
npm install --save-dev babel-plugin-transform-async-generator-functions
or
yarn add --dev babel-plugin-transform-async-generator-functions
Activate the plugin by creating a .babelrc file (or add to the file):
{ "plugins": ["transform-async-generator-functions"] }
Now your jest tests should work with async generators.

How to exeHicute angular unit test cases using Nodejs and Karma

I have created a unit test in angular js,However I have no idea on how to setup node.js and Karma
So I downloaded the node.js from nodejs.org and installed it.
Open the command prompt and installed karma by executing "npm install karma"
It installed karma.But when I execute my angular js unit test case,it reports some errors
angular is undefined.
I followed the instructions as mentioned in this
http://bardevblog.wordpress.com/2013/07/28/setting-up-angularjs-angular-seed-node-js-and-karma/
Is there any where how to setup Karma and node js to execute angular unit test cases.
Please provide me the information
You can use the Yeoman generator for an Angular.js app to generate a new project and see how it is done there. Please follow the steps under "Usage" on the GitHub page to set up the new project. (For all questions yo is asking just hit enter.) Finally, type grunt test:client. This executes Karma configured with the karma.conf.js.
In your karma config file you need to define all the js files that needs to be loaded and the order in which you specify then is important! Example:
files : [
'source/lib/angular/angular.js', // angular first
'source/lib/angular/*.js', // then any other angular files (angular-mocks.js, angular-resource.js, angular-route.js ...
'source/lib/x2js/xml2json.min.js', // some libraries I used
'source/lib/jquery/jquery.js',
'source/lib/ui-bootstrap/ui-bootstrap.js',
'source/js/*.js', // my own js code
'source/tests/unit/*.js' // unit tests
]

Trouble working with Karma

I am trying to use Karma with Mocha over a NodeJS project, and I get an error:
"Module name "TestStub" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded"
Not sure where am I supposed to add the test stub file.
In addition, when I configured Karma using "Karma init" I asked for being able to use requireJS, but don't where are the config files to be added to Karma. There's a config file for the tests and another one for the code and I'll need to include both.
Karma is for browser testing. If you want to test your server side nodejs code with karma, you will fail... Maybe you can do integration tests which can check the response of your nodejs application by hand-made http requests, but that's all...
Almost everything about how to use karma with requirejs is well documented here.

Exporting the same object that is required confuses mocha

I'm working on a node app that uses mocha to run unit tests.
When I run this command:
mocha --compilers coffee:coffee-script --reporter spec ./test/unit/*-test.coffee
I get this error:
ERROR: Unknown option --compilers
It seems mocha is confused, because it definitely has a compilers option. This error started happening when I added a new file to the project. It's the only output I can get mocha to generate. --debug does nothing.
Let's say I have a package called person installed. I want to configure this package globally so that I can import the configured object anywhere in my project. To do that, I import person, configure it as a driver, and then export it again.
However, when I import it (either in Car.coffee or Car-test.coffee), mocha fails with the above error.
Driver.coffee
driver = require 'person'
driver.setSkill "Drive"
module.exports = driver
Car.coffee
driver = require './driver'
...
Car-test.coffee
driver = require '../../src/driver'
...
Note that this works fine if I'm just compiling with coffee and running the node project. There's no issue importing it there. But when I run with mocha, it fails if I import the file.
I can't really pinpoint the error. It seems just like a bug in mocha, but maybe I'm doing something "bad" by exporting the same object that I import, and node is just more forgiving?
I'm using the latest version of mocha (1.13.0). Thanks!
Edit:
This doesn't fix the error, and is not ideal syntax-wise:
person = require 'person'
class driver
constructor: ->
person.setSkill "Drive"
#person = person
module.exports = driver
Note that simply wrapping it in a plain object doesn't work.
Edit 2:
Here's something else that doesn't work:
configure-driver.coffee
configureDriver = (person) ->
person.setSkill "Drive"
module.exports = configureDriver
car.coffee
driver = require('./configure-driver')(require 'person')
Mocha throws the same error as before.
Maybe a little late but hopefully it will help someone (I just spent an hour paging through mocha's source code to track this down).
Try that command instead (the important bit is the equal sign after --compilers):
mocha --compilers=coffee:coffee-script --reporter spec ./test/unit/*-test.coffee
I ran into that bug while trying to create a new grunt test taks using grunt-mocha-istanbul and coffeescript test definitions. Strangely, if I ran the command directly in my shell it worked but using the grunt task I got the same error as you did.
It seems Mocha uses commander and it's global. In my case I had a script under the test directory that uses commander. It looks like Mocha executes the test scripts, parses mocha.opts, and then executes the specs. To fix it I just moved the scripts using commander out of the test dir and all was good.

Resources