How to mock a function in Karma.js - javascript

Does somebody knows how to mock a function result with karma.js ?
The function uses a var given by thymeleaf framework (java, spring boot, etc..).
function isFlooring() {
var isMyChoiceOk = [[${mychoice}]];
if(typeof isMyChoiceOk !== 'undefined') {
return isMyChoiceOk;
}
else {
return false;
}
}
What I want to do is to tell karma.js that the result of this function is TRUE or FALSE.

You can create a spy on the function (this assumes your function isn't part of an object) and then replace it with your own function:
spyOn(window, 'isFlooring')
.and.callFake( function(arguments) {
// return whatever you want to here
return true
}
The spy just listens for that function to be called and then 'callFake' replaces the functionality with what you want it to be.
If your function is part of an object, replace 'window' in the 'spyOn' call with the name of the object.

Related

Jasmine conditional callThrough and callFake

I have a method which returns function references.
function methodetobeMoked(param){
case1:return func1;
case 2: return func2;
.
.
case n: return funcN;
}
I need to spy this method and return a fake function reference for a particular input param p
Is there any conditional callThrough in jasmine tests
My scenario is
SpyOn(some object,'someMethode').and.{if param=p callFake(fakeMethode) else callThrough()}
I tried callFake Is there any way to pass control to original method from fake method?
A Jasmine spy retains the original function in a property named originalValue, so you can do something like:
var mySpy = {};
mySpy = t.spyOn(obj, 'methodToBeMocked').and.callFake(function (param) {
if (param === 'fake case') {
// return fake result
} else {
// do this if using Jasmine
return (mySpy.and.callThrough())(param);
// do this if using Ext + Siesta and duped by common syntax :)
// return mySpy.originalValue(param);
}
});

Angular services with default values for non-existing attributes

Working on an Ionic application that performs both in Android and Windows.
There are services, such as Ionic's $ionicLoading, which we override functionality in order to work properly in windows:
angular.factory('$ionicLoading', function(){
return {
show: function (){...} // custom implementation
hide: function (){...} // custom implementation
}
});
But there are other services which we have to override only to not break the app.
In this cases it would be really useful to provide a service that won't do anything. For example:
angular.factory('$ionicExampleService', function(){
return {
*foo*: angular.noop // for operations
*bar*: promise // returns promise
}
});
Note: I know that a better way of doing this would be with a service that chooses between Ionic's implementation or a made one, but this is just for the sake of learning.
The ideal would be going even further, it would be magnificent to be able to return something even more bulletproof. Something like a generic flexible services:
angular.factory('$ionicPopup', function(){
return /*magic*/;
});
$ionicPopup.show({...}) // show was not defined
.then(foo); // won't break and will execute foo()
It is possible?
From what I understood you need to override implementation of existing services. You can do that with an angular service decorator.
A service decorator intercepts the creation of a service, allowing it to override or modify the behaviour of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service.
For more information you can check angular documentation. One simple example would be:
app.factory('someService', function () {
return {
method1: function () { return '1'; }
method2: function () { return '2'; }
};
});
app.decorator('someService', function ($delegate) {
// NOTE: $delegate is the original service
// override method2
$delegate.method2 = function () { return '^2'; };
// add new method
$delegate.method3 = function () { return '3'; };
return $delegate;
});
// usage
app.controller('SomeController', function(someService) {
console.log(someService.method1());
console.log(someService.method2());
console.log(someService.method3());
});
EDIT: Question - How to override every method in the service?
var dummyMethod = angular.noop;
for(var prop in $delegate) {
if (angular.isFunction($delegate[prop])) {
$delegate[prop] = dummyMethod;
}
}
I hope that this helps you.
Using an evaluation for each assignment based on an object property, similar to this:
myVar = myObj.myPropVar === undefined ? "default replacement" : myObj.myPropVar;
Basically you're using a check for if the property has been defined, substituting a default value if it hasn't, and assigning it if it has.
Alternatively, you can use a modified version of the global function in Sunny's linkback to define defaults for all those properties you might assume to be undefined at specific points in your code.
function getProperty(o, prop) {
if (o[prop] !== undefined) return o[prop];
else if(prop == "foo") return "default value for foo";
else if(prop == "bar") return "default value for bar";
/* etc */
else return "default for missing prop";
}
Hope that helps,
C§
use var a = {}; to declare new variable.

Javascript Initialization Closure

I'm trying to create javascript closure that will tell me if the function has already been run:
This is what I have so far:
function do()
{
var isInitialized = function()
{
var init = false;
if (init == false)
{
init = true;
return false;
}
return init;
}
if (!isInitialized())
{
// do stuff
}
}
My function isInitialized always evaluates to true. I'm like 90% sure I'm not setting the internal variable correctly. How do I fix my code?
First of all, you can't use do as your function name as that's a keyword.
Secondly, you can attach properties right to your function so you don't need a closure or anything like this:
function f() {
if(f.initialized)
return;
f.initialized = true;
console.log('Doing things.');
}
f();
f();
That will give you just one "Doing things." in the console.
Demo (run with your JavaScript console open): http://jsfiddle.net/ambiguous/QK27D/
Functions are objects in JavaScript so they can be assigned properties which provides a convenient mechanism for achieving what you want to do:
function doit() {
if (typeof doit.isInitialized === "undefined") {
doit.isInitialized = true;
// do stuff
}
}
Try this:
function fn(){
if (typeof fn.hasrun!='undefined'){return;}
fn.hasrun=true;
// do stuff
}
Every time you call isinitialized, it'll reset all the variables to default, so init will ALWAYS start out false. The values set afterwards are NOT carried over to the next time isInitialiazed is called.
What you want is a 'static' variable, which JS doesn't directly support, but can be simulated as per this answer: Static variables in JavaScript

javascript function modification

I am trying to write a logger object which logs messages to screen. here is my code.
http://github.com/huseyinyilmaz/javascript-logger
in every function that needs to log something, I am writing loggerstart and loggerEnd functions at start and end of my functions. But I want to run thos codes automaticalls for every function. is there a way to modify Function prototype so every function call can run automatically.
(I am not using any javascript framework.)
EDIT: Rewritten the function to make it more modular
Well, this is a creepy way to do it, but I use this way sometimes when I need overriding some functions. It works well, allows any kind of customization and easy to understand (still creepy).
However, you will need to have all your functions stored in some kind of global object. See the example for details.
function dynamic_call_params(func, fp) {
return func(fp[0],fp[1],fp[2],fp[3],fp[4],fp[5],fp[6],fp[7],fp[8],fp[9],fp[10],fp[11],fp[12],fp[13],fp[14],fp[15],fp[16],fp[17],fp[18],fp[19]);
}
function attachWrapperToFunc(object, funcName, wrapperFunction) {
object["_original_function_"+funcName] = object[funcName];
object[funcName] = function() {
return wrapperFunction(object, object["_original_function_"+funcName], funcName, arguments);
}
}
function attachWrapperToObject(object, wrapperFunction) {
for (varname in object) {
if (typeof(object[varname]) == "function") {
attachWrapperToFunc(object, varname, wrapperFunction);
}
}
}
And some usage example:
var myProgram = new Object();
myProgram.function_one = function(a,b,c,d) {
alert(a+b+c+d);
}
myProgram.function_two = function(a,b) {
alert(a*b);
}
myProgram.function_three = function(a) {
alert(a);
}
function loggerWrapperFunction(functionObject, origFunction, origFunctionName, origParams) {
alert("start: "+origFunctionName);
var result = dynamic_call_params(origFunction, origParams);
alert("end: "+origFunctionName);
return result;
}
attachWrapperToObject(myProgram,loggerWrapperFunction);
myProgram.function_one(1,2,3,4);
myProgram.function_two(2,3);
myProgram.function_three(5);
Output will be:
start,10,end,start,6,end,start,5,end
So generally it allows you to wrap each function in some object automatically with a custom written wrapper function.
You could call every function with a wrapper function.
function wrapper(callback) {
loggerstart();
callback();
loggerend();
}
And call it with wrapper(yourfunction);

Is there anyway to unit test javascript functions defined within a function?

I would just like to ask whether I would be able to unit test the code inside ExternalFunction within the document.ready? I have tried many things for a while now and still couldn't work out how, and am at my wits end.
$(document).ready(function () {
var originalExternalFunction = ExternalFunction;
ExternalFunction = function(context, param) {
// trying to unit test the stuff in here!
}
}
I'm unit testing using JsTestDriver. Test declaration is something like TestThisTest.prototype.test_this - function() {};
Thanks in advance.
Since, in your example, ExternalFunction is not declared within the scope of the function, it is global (or at least, in whatever scope it may have been defined in outside ready). You can therefore test it by calling it as a global.
The trouble is, in order to assign the function to ExternalFunction, you have to run ready (which you could run manually, if you need). This means that if you put any other functionality in ready, then no, it is not unit testable. If your example code is an accurate reflection of reality, then I suppose it is kinda testable.
The point of a construct like this, is to hide the inner function. If you don't wish to hide it, then Anon.'s suggestion of defining newExternalFunction in a more accessible scope is what you need.
If your function needs to be a closure using variables from within ready, you could define newExternalFunction thus:
var newExternalFunction;
$(document).ready(function () {
var originalExternalFunction = ExternalFunction;
newExternalFunction = function(context, param) {
// trying to unit test the stuff in here!
}
ExternalFunction = newExternalFunction;
}
You would still need to ensure that ready has run, prior to unit testing, but you wouldn't have to rely on ExternalFunction not being reset to originalExternalFunction.
You could do something like:
function newExternalFunction(context, param) {
//etc.
}
$(document).ready(function () {
var originalExternalFunction = ExternalFunction;
ExternalFunction = newExternalFunction;
}
Then it's relatively straightforward to run your unit tests on newExternalFunction.
Theoretically, you could do something like:
ExternalFunction = function() { }
ExecuteDocumentReady(); // implement a mock on $(document).ready(fn) to store the function, and then execute it here
ExternalFunction(fakeContext, fakeParam);
assert(fakeContext.foo == 12); // or whatever you need it to do
That being said, I'm not sure exactly how to do that in javascript.
You could use a closure to generate your callback function:
// create function to make your "extension" function
function createHookFunction(callback) {
// return a function
return function(context, param) {
var ret;
// // trying to unit test the stuff in here!
if (typeof callback == 'function') {
// if you want to trap the return value from callback,
// ret = callback.apply(...);
callback.apply(this, arguments);
}
return ret;
};
}
// your hook now becomes:
$(document).ready(function() {
ExternalFunction = createHookFunction(ExternalFunction);
});
// and your unit test becomes:
var funcToTest = createHookFunction();
funcToTest(testContext, testParam);
// And, you could even test that the callback itself gets called
function someTest() {
var testContext = {}, testParam='test';
var callbackCalled = false;
var funcToTest = createHookFunction(function(context, param) {
callbackCalled = (context === testContext) && (param === testParam);
});
return (funcToTest(testContext, testParam) == 'Expected Return') && callbackCalled;
}

Categories

Resources