Recently I had a problem, I couldn't find a way to test private function which was called as a callback from another file.

Let's assume that we have one library like this:

/*global window*/
var executeFunctionToBeCalledAsCallBack;
(function (ns) {
	"use strict";
	var myLocalFunctionToBeCalledAsCallBack;

	function myCallBack(functionToBeCalledAsCallBack) {
		myLocalFunctionToBeCalledAsCallBack = functionToBeCalledAsCallBack;
	}

	function executeFunctionToBeCalledAsCallBack(){
		myLocalFunctionToBeCalledAsCallBack();
	}

	function MyCallbackTest() {
		return {
			myCallBack: myCallBack,
			executeFunctionToBeCalledAsCallBack: executeFunctionToBeCalledAsCallBack
		};
	}
	
	ns.MyCallbackTest = MyCallbackTest;
	ns.myTest = new MyCallbackTest();
}(window));

Here notice first private variable myLocalFunctionToBeCalledAsCallBack, then notice method myCallback that it is assigning his parameter to local variable, and then execution of that variable which is expected to be function, in method executeFunctionToBeCalledAsCallBack. With the line ns.myTest = new MyCallbackTest(); I just created global variable which later I will use to execute my callbacks.

Now, let's use that my "library":

/*global document, window*/
(function (ns) {
    "use strict";

    function myPrivateFunction() {
        document.querySelector("#myTest").innerHTML = "test";
    }

    function ExecuteMyTest (myTest) {
        myTest.myCallBack(myPrivateFunction);
        myTest.executeFunctionToBeCalledAsCallBack();
    }

    ns.ExecuteMyTest = ExecuteMyTest;
}(window));

Here notice two lines:
  myTest.myCallBack(myPrivateFunction);
  myTest.executeFunctionToBeCalledAsCallBack();

With first line I will assign function to local, private, variable, with second I will execute that function.

HTML looks like this:

<!DOCTYPE html>
<html>

<head>
    <script type="text/javascript" src="/sm.namespaces.js"></script>
    <script type="text/javascript" src="/sm.functions.js" defer></script>
    <script type="text/javascript" src="/sm.index.js" defer></script>
</head>

<body>
<div id="myTest"></div>
<button id="myButton" onClick="window.ExecuteMyTest(window.myTest)">Click Me!</button>
</body>

</html>

Now, we should write a test. Problem is that we can't access prvate function so easy. This is my test:

/*global describe, beforeEach, document, expect, it, window, myTest, jasmine*/
describe("call fake test", function () {
	"use strict";
	var sut,
		myTest;
	beforeEach(function () {
		var myDiv = document.createElement('div'),
			functionToBeCalledAsCallBackTest;
		myDiv.setAttribute("id", "myTest");
		document.body.appendChild(myDiv);
		sut = window.ExecuteMyTest;
		myTest = jasmine.createSpyObj("myTest", ["myCallBack", "executeFunctionToBeCalledAsCallBack"]);
		myTest.myCallBack.and.callFake(function (functionToBeCalledAsCallBack) {
			functionToBeCalledAsCallBackTest = functionToBeCalledAsCallBack;
		});
		sut(myTest);
		functionToBeCalledAsCallBackTest();
	});


	it("div text should be test", function () {
		expect(document.querySelector("#myTest").innerHTML).toBe("test");
	});

	it("expect to be called", function () {
		expect(myTest.myCallBack).toHaveBeenCalled();
	});
});

Here notice first part of code:

myTest = jasmine.createSpyObj("myTest", ["myCallBack", "executeFunctionToBeCalledAsCallBack"]);
myTest.myCallBack.and.callFake(function (functionToBeCalledAsCallBack) {
  functionToBeCalledAsCallBackTest = functionToBeCalledAsCallBack;
}); 

First we created spy object, then we assigned parameter to our local variable, and then we executed that variable, expecting to be a function, with line:

functionToBeCalledAsCallBackTest();

Also, notice code:

myDiv = document.createElement('div'),

and then:

myDiv.setAttribute("id", "myTest");
document.body.appendChild(myDiv);

With part of code I created a div, which will be filled after execution of private function, I need that part to be able to test functionality...

Best would be if we look our tests with Karma coverage report to see how much we covered our code, just comment out line functionToBeCalledAsCallBackTest();, and check karma. 

Here is how my package looks like:

{
  "name": "jasmineExample",
  "version": "0.0.1",
  "devDependencies": {
    "karma": "^0.12.31",
    "karma-chrome-launcher": "^0.1.7",
    "karma-cli": "0.0.4",
    "karma-coverage": "^0.2.7",
    "karma-jasmine": "^0.3.5"
  }
}

Karma config looks like this:

/*global module*/
module.exports = function(config) {
    "use strict";
    config.set({
        basePath: "..",
        plugins: ['karma-chrome-launcher', 'karma-coverage', 'karma-jasmine'],
        frameworks: ['jasmine'],
        files: [
            'sm.namespaces.js',
            'sm.functions.js',
            'sm.index.js',
            'tests/spec/index.spec.js'
        ],

        // coverage reporter generates the coverage
        reporters: ['progress', 'coverage'],
        browsers: ['Chrome'],
        singleRun: true,

        preprocessors: {
            // source files, that you wanna generate coverage for
            // do not include tests or libraries
            // (these files will be instrumented by Istanbul)
            'sm.index.js': ['coverage'],
            'sm.functions.js': ['coverage']
        },

        // optionally, configure the reporter
        coverageReporter: {
            type : 'html',
            dir : 'coverage/'
        }
    });
};

Here notice line:

basePath: "..",

I had to add this line, otherwise if in files section I write something like:

'../sm.namespaces.js',

Karma will loose his path, and it will not be able to load css files anymore.

This my little example, you can see here, jasmine tests are here, everything together you can download from here, but you will have to install karma, go to subfolder tests (in my case that is C:\Users\pera.virtualOne\Downloads\jasmine\tests) execute following command:

npm install

and start Karma with:

karma start karma.conf.js

Now in upper folder you should see coverage folder, in my case here C:\Users\pera.virtualOne\Downloads\jasmine\coverage, go there and execute index.html.