Hi Am new to using Jasmine. The issue is as follows: I have a number of modules, managed through RequireJS. Now a module A creates an instance of another module B in it. Is it possible to use Jasmine to test whether an instance of B is being created in A? To convey a clearer idea of the code, we have:
//In module A
define(['B',],function(B){
function test(){
var newTest = new B();
};
return {test: test};
});
Now, how do i use Jasmine to test that module A indeed, creates an instance of module B? Thanks in advance!
Regards
Here's one way to check the type of an object in a Jasmine test:
describe('ChocolateFactory', function() {
it('creates an instance of Chocolate', function() {
var factory = new ChocolateFactory();
var chocolate = factory.makeChocolate();
expect(chocolate instanceof Chocolate).toBe(true);
});
});
Related
Hi I found a framework where they use a lot this pattern.
exports.install = function(){
//code
}
but usually you see this pattern in nodejs
module.exports = {
//code
}
Is this the same thing or is this something else ?
exports is the object corresponding to module.exports before you do anything to it. I think it's due to some legacy code, but basically folks use module.exports if they want to replace the whole object with their own object or a function, while they use exports if they just want to hang functions off the module. It's a little confusing at first, but essentially exports.install just means that calling code would do something like:
const mod = require('that-module');
mod.install(params, callback); // call that function
The framework you're looking at is probably using it as part of a bootstrapping process, afaik it doesn't have significance to the node engine itself.
Yes, it is the same thing. You can use one of 2 ways to setup your code.
The different thing is memory. They point to same memory. You can think exports like a variable and you can not use this way to export your module:
Given this module:
// test.js
exports = {
// you can not use this way to export module.
// because at this time, `exports` points to another memory region
// and it did not lie on same memory with `module.exports`
sayHello: function() {
console.log("Hello !");
}
}
The following code will get the error: TypeError: test.sayHello is not a function
// app.js
var test = require("./test");
test.sayHello();
// You will get TypeError: test.sayHello is not a function
The correct way you must use module.exports to export your module:
// test.js
module.exports = {
// you can not use this way to export module.
sayHello: function() {
console.log("Hello !");
}
}
// app.js
var test = require("./test");
test.sayHello();
// Console prints: Hello !
So, it just is style of developer.
I am currently testing a module in isolation using proxquire to overwrite a require of this module.
Overwriting a path of a require works fine with proxyquire. For example:
var bar = require('./bar');
But can you use proxyquire also to overwrite just a specific function of a module which is required in the module to test? So something like:
var bar = require('./foo').bar();
I need to stay at proxyquire for this since I am using it for mocking a http-request happening in another layer of the architecture. But in case of the test I need to mock the time for "now" in the module as well.
So currently I have this:
var uraStub = sendMockRequest(paramListOfCheckin, queryList);
var setNowStub = function(){ return 1425998221000; };
var checkin = proxyquire('../src/logic/logicHandlerModules/checkin', {
'../../persistence/ura' : uraStub,
'./checkin.setNow' : setNowStub
});
checkin.checkin(...)
The implementation of setNow is:
var setNow = function(){
return new Date().getTime();
};
var checkin = function (...) {
var now = require('./checkin').setNow();
Obviousley './checkin.setNow' : setNowStub in proxyquire doesn't work, since this is the wrong path. But using './checkin'.setNow() : setNowStub also doesn't work because of wrong syntaxis in the object-definition.
Any suggestions?
Thanks in advance!
What you are looking for is the noCallThru() and callThru() methods. https://github.com/thlorenz/proxyquire#preventing-call-thru-to-original-dependency
By default proxyRequire will call through to the mocked dependency which will allow you to pick the methods that you want to overwrite with your own custom function.
So if a dependency in the path '../foo' has a method bar() and fooBar() you would be able to mock out just bar by doing.
proxyquire.callThru();
var fooFunc = proxyquire('../foo', {
bar: () => return 'bar'
})
Now bar() will hit your custom overwritten funtion while fooBar() will be called as normal.
I am new to nodejs, and need to write unit test for a node project. I try to learn mocha and there are two questions:
when I write unit test for function A, in A it also use function B, so how can I mock an output for B?
how can I unit test these endpoints in app.js. like app.get, app.put.
can someone give me some suggestions or simple examples?
Can someone also give me some advice on writing unit test for nodejs, thanks so much.
Thanks so much everyone.
Answering Q1,
If the output of b method is used in a metheod, then you can make the test of b method first.
Otherwise you can prepare result of b in before section of your test method and use it in a method.
It depends on your approach of testing.
Answering Q2 -
You can use superagent for sending get or post request ...
Some code examples ...
require('should');
var assert = require("assert");
var request = require('superagent');
var expect = require('expect.js');
then,
describe('yourapp', function(){
before(function(){
// function start
start your server code
// function end
})
describe('server', function(){
describe('some-description', function(){
it('should return json in response', function(done){
request.post('http path')
.send(JSON.parse("your json"))
.end(function(res){
expect(res).to.exist;
expect(res.status).to.equal(200);
expect(res.text).to.contain('ok');
done();
});
})
});
})
after(function(){
//stop your server
})
});
Here done is an important aspect in a unit testing component for asynchronous method testing.
Some reference -
superagent
this blog post
Hope this will help you,
Thanks
Answering Q1,
If the funcitons in different modules,
You can use a mock tool : fremock
Using freemock You can do this:
your code
//function a exports in the module named mA
function a(){
return "1";
}
//function a exports in the module named mB
function b(){
a();
}
test code
var freemock = require('freemock');
freemock.start()
var mock_b = freemock.getMock('mB');
mock_b.setMethod({
"a":{
willReturn:"1"
}
})
freemock.end();
Some advice:
Mocha is good test framework for node.js .
For example,
Assert tool: should.js
Code coverage tool:istanbul
...
Mocha combines all this tools;
Here is a demo using Mocha:
your code(filename:mA.js)
//in the module named mA
function a(){
return true;
}
test code(filename:testmA.js)
var should = require('should');
beforeEach(function(){
//do something before testing
});
afterEach(function(){
//do something after testing
});
describe("test",function(){
describe("test1",function(){
it("if true",function(){
var mA = require('./mA');
var result = mA.a();
should.ok(result);
});
it("if false",function(){
//other test
});
});
describe("test2",function(){
it("test2-1",function(){
//other test
})
})
})
We should need run.js to start the test:
//run.js
var Mocha = require('mocha');
var mocha = new Mocha;
mocha.addFile(__dirname+'/test/testmA.js')
mocha.run();
The project dir tree is:
|- run.js
|
|- mA.js
|
|- test - testMA.js
Finally
Run this command:
istanbul cover run.js
Hope you enjoy!
I am recently involved in a node project where I have to run unit tests.
Eventually I wrote a small script runner for karma using NW.JS
This allowed me to access all node modules and run my tests on the server itself. I uploaded this project to github, Narma.
Right now it was only tested on a Mac
I'm trying to spy on dependencies in a Node.js module from within a Jasmine spec, and I'm encountering some weird behaviour.
Jasmine spies on a method that resides in an object exposed by the exports object in the module. When I call the spied-on method in the module using
exports.umap()
the spy detects it. But when I call it in the module using a variable name I assigned to the same method
var umap = exports.umap
umap()
the spy doesn't detect it.
This seems weird to me given that var umap refers to the same method as exports.umap. Anyone have any ideas why this is? Code below.
(The whole reason I'm doing this is that I want to stub my module's dependencies without the need to design the module as a class and use dependency injection.)
// mapper.js
exports.umap = require('underscore').map;
var umap = exports.umap;
function map () {
return exports.umap([1,2,3], function(el) {console.log(el);return el * 2});
// umap() goes unnoticed by the spy
// return umap([1,2,3], function(el) {console.log(el);return el * 2});
}
exports.map = map;
.
// mapper_spec.js
var mapper = require ('../../lib/mapper');
var map = mapper.map;
describe('mapper', function() {
describe('map', function() {
it('calls umap', function() {
var mapped;
spyOn(mapper, 'umap').and.callThrough();
mapped = mapper.map();
expect(mapper.umap).toHaveBeenCalled();
expect(mapped).toEqual([2,4,6]);
});
});
});
UPDATE
I'm still curious about this issue, however https://www.npmjs.org/package/proxyquire made my whole "spying-on-things-attached-to-export-object" strategy moot.
Writing the simplest module we could, we write into hello.js:
var hello = function(){
console.log('hello');
};
exports = hello; \\ Doesn't work on Amazon EC2 Ubuntu Instance nor Windows Powershell
I run Node and require the module
var hello = require('./hello');
hello;
and an empty array {} gets returned when I'm supposed to get [Function].
I tried replacing exports with module.exports, but this doesn't work on my Windows Powershell. It does work on my Amazon EC2 Ubuntu Instance, so why doesn't exports work? Has the API changed? And what could possibly be happening with Powershell that neither of these work?
I know Windows isn't the most desirable development environment, but I can't get my head around such a simple mishap.
EDIT
exporting with ES6 is a little nicer
export const hello = function(){
console.log('hello');
};
importing will look like
import {hello} from './file';
Original answer
You'll want to use module.exports
var hello = function(){
console.log('hello');
};
module.exports = hello;
If just exporting one thing, I'll usually do it all in one line
var hello = module.exports = function() {
console.log('hello');
};
Extras
If you use a named function, in the event an error occurs in your code, your stack trace will look a lot nicer. Here's the way I would write it
// use a named function ↓
var hello = module.exports = function hello() {
console.log("hello");
};
Now instead of showing anonymous for the function name in the stack trace, it will show you hello. This makes finding bugs so much easier.
I use this pattern everywhere so that I can debug code easily. Here's another example
// event listeners ↓
mystream.on("end", function onEnd() {
console.log("mystream ended");
};
// callbacks ↓
Pokemon.where({name: "Metapod"}, function pokemonWhere(err, result) {
// do stuff
});
If you want to export multiple things, you can use exports directly, but you must provide a key
// lib/foobar.js
exports.foo = function foo() {
console.log("hello foo!");
};
exports.bar = function bar() {
console.log("hello bar!");
};
Now when you use that file
var foobar = require("./lib/foobar");
foobar.foo(); // hello foo!
foobar.bar(); // hello bar!
As a final bonus, I'll show you how you can rewrite that foobar.js by exporting a single object but still getting the same behavior
// lib/foobar.js
module.exports = {
foo: function foo() {
console.log("hello foo!");
},
bar: function bar() {
console.log("hello bar!");
}
};
// works the same as before!
This allows you to write modules in whichever way is best suited for that particular module. Yay!
The reason exports is not working is because of the reference conflict. The top variable in each file is module which has a property module.exports. When the module is loaded new variable is created in the background. Something like this happens:
var exports = module.exports;
Obviously exports is a reference to module.exports, but doing
exports = function(){};
forces exports variable to point at function object - it does not change module.exports. It's like doing:
var TEST = { foo: 1 };
var foo = TEST.foo;
foo = "bar";
console.log(TEST.foo);
// 1
Common practice is to do:
module.exports = exports = function() { ... };
I have no idea why it doesn't work under Windows Powershell. To be honest I'm not even sure what that is. :) Can't you just use native command prompt?