I have a situation where there are many mocked http requests. While working on angular upload, something fishy happening in my case. It is always throwing status:200 success and html complete body response.
Below is my angular upload code:
function fileUploadController(FileUploader) {
/* jshint validthis: true */
let vm = this;
vm.type = this.type;
vm.clientId = this.client;
let uploader = new FileUploader({
url: 'http://localhost:8001/prom-scenario-config/files?clientId=' + vm.clientId,
data: {type: vm.type}
});
vm.uploads = {uploader};
vm.upload = upload;
vm.uploads.uploader.queue = [];
vm.uploads.uploader.onCompleteItem = function (item, response) {
let type = item.uploader.data.type;
console.log('response => ', response);
};
}
mock of httpbackend code looks like this:
$httpBackend.whenPOST(new RegExp('http://localhost:8001/prom-scenario-config/files\\?clientId=([a-zA-Z0-9-])$$'))
.respond(function () {
return [200, 'foo'];
});
But there is no affect on this.
Is there any error in my regex code in constructing?
With or without having the mock code. Still the response i am receiving is 200.
There are so many mock requests, i am facing difficulty in identifying which request is being called.
Is there any tricky way to identify which regex call is called? Or enforce my request to mock?
Below is the reference for status and response FYI.
Unit test suppose that a unit is tested in isolation. Any other thing which is not a tested unit, i.e. a controller should be mocked, especially third-party units.
Considering that it is tested with Jasmine, FileUpload service should be stubbed:
beforeEach(() => {
// a spy should be created inside beforeEach to be fresh every time
module('app', { FileUpload: jasmine.createSpy() });
});
And then controller is tested line by line like:
it('...', inject(($controller, FileUpload) => {
const ctrl = $controller('fileUploadController');
...
expect(FileUpload).toHaveBeenCalledTimes(1);
expect(FileUpload).toHaveBeenCalledWith({ url: '...', type: {...} });
// called with new
const fileUpload = FileUpload.calls.first().object;
expect(fileUpload instanceof FileUpload).toBe(true);
expect(ctrl.fileUpload).toBe(fileUpload);
expect(fileUpload.onCompleteItem).toEqual(jasmine.any(Function));
expect(fileUpload.queue).toEqual([]);
...
}));
In the code above clientId=([a-zA-Z0-9-]) regexp part matches only ids consisting of a single character, which isn't true. That's why it is preferable to hard-code values in unit tests, human errors are easier to spot and detect. It's not possible to unambiguously identify the problem when the tests are too loose, this results in wasted time.
Related
I am currently new to Sinon, Mocha, Supertest and in the process to writes tests. In my current scenario, i have authentication library which verifies my "OTP" and after verifying it proceeds to do operation within the callback function.
I am unable to mock the callback to return null and carry on to test rest of the code. Following is my code snippet:
Controller.js
var authy = require('authy')(sails.config.authy.token);
authy.verify(req.param('aid'), req.param('oid'), function(err, response) {
console.log(err);
if (err) {
return res.badRequest('verification failed.');
}
....
My test is :
var authy = require('authy')('token');
describe('Controller', function() {
before(function() {
var authyStub = sinon.stub(authy, 'verify');
authyStub.callsArgWith(2, null, true);
});
it('creates a test user', function(done) {
// This function will create a user again and again.
this.timeout(15000);
api.post('my_endpoint')
.send({
aid: 1,
oid: 1
})
.expect(201, done);
});
});
I essentially want to call authy verify get a null as "err" in callback, so i can test the rest of the code.
Any help would be highly appreciated.
Thanks
The trouble is that you're using different instances of the authy object in your tests and your code. See here authy github repo.
In your code you do
var authy = require('authy')(sails.config.authy.token);
and in your test
var authy = require('authy')('token');
So your stub is generally fine, but it will never work like this because your code does not use your stub.
A way out is to allow for the authy instance in your controller to be injected from the outside. Something like this:
function Controller(authy) {
// instantiate authy if no argument passed
in your tests you can then do
describe('Controller', function() {
before(function() {
var authyStub = sinon.stub(authy, 'verify');
authyStub.callsArgWith(2, null, true);
// get a controller instance, however you do it
// but pass in your stub explicitly
ctrl = Controller(authyStub);
});
});
I am writing test cases for NODE JS API. But wherever console.log() is there in routes or services of NODE JS File, it gets printed to CLI. Is there a way to mock these so that these won't get printed in CLI.
I have explored couple of libraries like Sinon, Stub for mocking. But couldn't grasp the working of those libraries.
You can override function entirely: console.log = function () {}.
You should not try to mock console.log itself, a better approach is for your node modules to take a logging object. This allows you to provide an alternative (ie. a mock) during testing. For example:
<my_logger.js>
module.exports = {
err: function(message) {
console.log(message);
}
}
<my_module.js>
var DefaultLogger = require('my_logger.js');
module.exports = function(logger) {
this.log = logger || DefaultLogger;
// Other setup goes here
};
module.exports.prototype.myMethod = function() {
this.log.err('Error message.');
};
<my_module_test.js>
var MyModule = require('my_module.js');
describe('Test Example', function() {
var log_mock = { err: function(msg) {} };
it('Should not output anything.', function() {
var obj = new MyModule(log_mock);
obj.myMethod();
});
});
The code here I've simplified, as the actual test isn't the reason for the example. Merely the insertion of alternative logging.
If you have a large codebase with lots of console.log calls, it is better to simply update the code as you add tests for each method. Making your logging pluggable in this way makes your code easier and more receptive to testing. Also, there are many logging frameworks available for node. console.log is fine during development when you just want to dump out something to see what's going on. But, if possible, try to avoid using it as your logging solution.
I could not find a solution which only hides the console.log calls in the module to be tested, and mocks none of the calls of the testing framework (mocha/chai in my case).
I came up with using a copy of console in the app code:
/* console.js */
module.exports = console;
/* app.js */
const console = require('./console');
console.log("I'm hidden in the tests");
/* app.spec.js */
const mockery = require('mockery');
var app;
before(() => {
// Mock console
var consoleMock = {
log: () => {}
}
mockery.registerMock('./console', consoleMock);
// Require test module after mocking
app = require('./app');
});
after(() => {
mockery.deregisterAll();
mockery.disable();
});
it('works', () => {});
You could do something along the lines of adding these before/after blocks to your tests, but the issue is that mocha actually uses console.log to print the pretty messages about the results of the test, so you would lose those
describe('Test Name', function() {
var originalLog;
beforeEach(function() {
originalLog = console.log;
console.log = function () {};
});
// test code here
afterEach(function() {
console.log = originalLog;
})
})
The problem is that your output would just look like
Test Name
X passing (Yms)
Without any intermediate text
I have the following JavaScript:
var async = require('async');
var MyOutputModel = function(persistenceModel, callback) {
async.each(persistenceModel.helpOffers, function(helpOffer, asyncCallback) {
console.log('Original source (loop)');
//Do something ...
asyncCallback();
}, function(err) {
console.log('Original source (done)');
console.log(err);
if(err) return callback(err);
return callback(null, _this);
});
};
module.exports = MyOutputModel;
I would like to test the path containing if(err) return callback(err);...
For doing so I see the only possibility in dependency injection with rewire (https://www.npmjs.com/package/rewire).
In my unit test:
var rewire = require('rewire');
var MyOutputModel = rewire('...');
var AsyncMock = function() {};
AsyncMock.prototype.each = function(array, successCallback, errorCallback) {
console.log('Inside mock!');
callback(new Error());
};
var asyncMock = new AsyncMock();
MyOutputModel.__set__('async', asyncMock); //Rewire for require-dependency-injection
//Act
new CdObjectOutputModel(cdObjectPersistenceModel, function(err, cdObjectOutputModel) {
//Assert
assert(err);
});
However the "mock" doesn't seem to be used. In my unit test I never see 'Inside mock!' but 'Original source (loop)' and 'Original source (done)' on the console. And there is no error.
Anything I do wrong? I've already used rewire for a similar use case and it worked perfectly. Or is there another approach?
This is what rewire does under the hood:
For each rewired path it'll actually read the contents of the file pointed by path which we will call the body
it'll also generate two strings, the first one is called the prelude and it has some helpful vars to avoid overwriting the global ones with __set__, e.g. if we wanted to override the global console as if it were local on our module the contents of the prelude var would be: var console = global.console, this awesome detection of globals which can be overridden locally is done here
The second one is called the appendix and this string contains actually the definitions of the __set__, __get__ and there's also __with__ source, each one is a function defined over module.exports but remember that we're still dealing with strings
Imagine that there's a way to create a fake/test module out of strings! That's what wired does, it concatenates the prelude, the body and the appendix in one big string and it then creates a module with require('module')
e.g. (remember that this is a big string)
// prelude start
var console = global.console
// a lot of globals that can be overriden are defined here :)
// prelude end
// body start
// I'll paste the contents of the rewire's README
var fs = require("fs");
var path = "/somewhere/on/the/disk";
function readSomethingFromFileSystem(cb) {
console.log("Reading from file system ...");
fs.readFile(path, "utf8", cb);
}
exports.readSomethingFromFileSystem = readSomethingFromFileSystem;
// body end
// appendix start
// generation of three functions to set the variables defined above
Object.defineProperty(module.exports, '__set__', {
enumerable: false,
value: function () {
// set contents, we will see this later
}
});
Object.defineProperty(module.exports, '__get__', { ... });
Object.defineProperty(module.exports, '__with__', { ... });
// appendix end
So what rewire does is kind of create a module with this string and return it, and voila you have a magic module with three additional properties, the next step is actually find out what __set__ does, the __set__ source boils down to the following operation:
function (key, value) {
eval(key + ' = ' + value);
}
And that's it so now we know that executing __set__ will just eval whatever key (which for us is any local var) you want, to be set as value but ONLY in this test/fake module.
Now going back to your problem I see that this might be the source of it:
new CdObjectOutputModel(...);
I'm assuming that CdObjectOutputModel is defined perhaps as a subclass of MyOutputModel but remember that in your test var MyOutputModel = rewire('...'); is actually a test/fake module so you're not really overriding the original code of MyOutputModel but overriding kind of a copy of it which exists only locally, I guess that you have to rewire CdObjectOutputModel or perhaps locally make CdObjectOutputModel inherit from the rewired version of MyOutputModel
Just replace callback with errorCallback and it should work fine.
I'm writing unit tests for a store in a react+flux app. I followed the example of setting up the mock dispatcher here, and my unit test looks like this:
jest.dontMock "../../app/scripts/stores/item_store.coffee"
jest.dontMock "object-assign"
describe 'ItemStore', ->
ShopConstants = require "../../app/scripts/constants/shop_constants.coffee"
ShopDispatcher = undefined
ItemStore = undefined
callback = undefined
actionBuildQueryString =
source: "VIEW_ACTION"
action:
type: ShopConstants.ActionTypes.BUILD_QUERY_STRING
size: "4"
actionReceiveFilterRespData =
source: "SERVER_ACTION"
action:
type: ShopConstants.ActionTypes.RECEIVE_FILTER_RESP_DATA
data: {item: {} }
beforeEach ->
ShopConstants = require "../../app/scripts/constants/shop_constants.coffee"
ShopDispatcher = require "../../app/scripts/dispatchers/shop_dispatcher.coffee"
ItemStore = require "../../app/scripts/stores/item_store.coffee"
callback = ShopDispatcher.register.mock.calls[0][0]
it "registers a callback with the dispatcher", ->
expect(ShopDispatcher.register.mock.calls.length).toBe(1)
In my item_store.coffee file, I register with the dispatcher as so:
ShopDispatcher.register (payload) ->
action = payload.action
switch action.type
when ActionTypes.BUILD_QUERY_STRING
WebApiUtils.fetchItems(payload)
when ActionTypes.RECEIVE_FILTER_RESP_DATA
_setItems(action.data)
ItemStore.emitChange()
I expected the mocked Dispatcher to register the callbacks since that happens in the actual item_store file, which I have told jest to not mock. However, since ShopDispatcher.register is undefined, it's not being registered, but I am not quite sure why. Any help is appreciated.
I was also facing the same problem. Instead of using the ShopDispatcher.register.mock.calls[0][0] try the ShopDispatcher.dispatch. the below code working perfectly for me (using type script).
beforeEach(function () {
dispatcher = require("../../../src/App/Dispatcher");
localeStore = require("../../../src/stores/localestore");
localeAction = require("../../../src/actions/Locale/LocaleAction");
}
it("should translate the element with the value in current locale JSON", function () {
localeChangeAction = new localeAction(true, locale, localeJson);
dispatcher.dispatch(localeChangeAction);
var translatedText = localeStore.instance.TranslateText("login.login-header");
expect(translatedText).toEqual("Login header");
});
I have the following code
index: function (req, res) {
var Request = unirest.get("https://poker.p.mashape.com/index.php?players=4").headers({ "X-Mashape-Authorization": "xxxxxxxxxxxxxxxxx" }).end(function (response) {
players = response.body;
showdown_total = players.showdown.length;
showdown = Array();
});
console.log(players);
// Send a JSON response
res.view({
hello: 'world',
//players: players
});
},
It works great if I add the res.view inside unirest get, but I want to send those variables to the view and be able to add another unirest request
Thanks for your help
That is how asynchronous code works in Node.js.
Basically, when an operation doesn't evaluate ASAP, node doesn't wait for it. It just says, "fine, no worries, just tell me when you are done".. sort of.
The thing is, in your code, you don't tell node when your get request. is done. You just fire away the view to the client before the request function even starts thinking about fetching the data.
How to make node wait ?
You have some options. Either, give it a callback function (do this when you are done), or you have to nest your functions. Those two are kind of the same thing really.
I'll show you one solution, nested functions:
var urlOne = "https://poker.p.mashape.com/index.php?players=4",
urlTwo = "http://some.other.url",
headers = { "X-Mashape-Authorization": "xxxxxxxxxxxxxxxxx" };
// Run first request
unirest.get(urlOne).headers(headers).end(function (response) {
players = response.body;
showdown_total = players.showdown.length;
showdown = Array();
// Run second request
unirest.get(urlTwo).headers(headers).end(function (response) {
someVar = response.body;
// Show all my data to the client
res.view({
players: players,
someOther: someVar
});
});
});
Other solutions:
If you don't want to nest the functions, give them a callback to run when they are done.
Use a module for handling asynchronous code, for example one of the more popular ones called Async.
I would suggest you to read more about callbacks, asynchronous code and nodejs before jumping directly on the external libraries.
There is another way....you could use fibers!
Read some docs here!
var sync = require('synchronize');
index: function (req, res) {
sync.fiber(function(){
var response = sync.await(
unirest.get("https://poker.p.mashape.com/index.php?players=4").headers(
{ "X-Mashape-Authorization": "xxxxxxxxxxxxxxxxx" }
).end(sync.defer())
);
var players = response.body;
console.log(players);
// Send a JSON response
res.view({
hello: 'world',
players: players
});
});
}