paniclater paniclater - 4 months ago 14x
Javascript Question

How to test 'private' functions in an angular service with Karma and Jasmine

I have a service in my angular app that looks something like this:

angular.module('BracketService', []).factory('BracketService', [function() {
function compareByWeight(a, b) {
return a.weight - b.weight;
function filterWeightGroup(competitors, lowWeight, highWeight) {
//filter stuff
function createBracketsByWeightGroup(weightGroup) {
//create some brackets
//set some base line values
return {
//create brackets from a list of competitors
returnBrackets: function(competitors) {
var brackets = {};
//get super light weights
brackets.superLightWeights = createBracketsByWeightGroup(
filterWeightGroup(competitors, 0, SUPER_LIGHT_WEIGHT)
brackets.superHeavyWeights = createBracketsByWeightGroup(
filterWeightGroup(competitors, SUPER_HEAVY_WEIGHT, Infinity)
brackets.middleWeights = createBracketsByWeightGroup(
filterWeightGroup(competitors, SUPER_LIGHT_WEIGHT, SUPER_HEAVY_WEIGHT)
return brackets;


I would like to unit test not just the functions / properties that are exposed in the return statement, but also the functions that are outside of the return statement.

My test is currently set up something like this:

describe('BracketService', function() {

it('calling return brackets with no competitors will return 3 empty weight classes', inject(function(BracketService) {
var mockCompetitors = [];
var mockBracketResult = {superHeavyWeights: [[]], superLightWeights: [[]], middleWeights: [[]]};

But how do I test the compare, filter and createBrackets functions that are not exposed by the return statement?



There is no way to test those functions. Their scope is the function that comprises your BracketService factory and they are invisible anyplace else. If you want to test them, then you have to expose them somehow.

You can move them into their own service (which seems like overkill) or you can black box test your BracketService service with enough data combinations to make sure the internal functions are working. That's probably the most sensible approach.

If you really feel the need to test those internal functions, return them from the factory along with returnBrackets.

I might do this when a have a number of helper functions that are straight forward to test individually, but open up a combinatorial Pandora's box to black box test. I usually preface such functions with an "_" to show they are helper functions and are only exposed for testing.

return {
    //create brackets from a list of competitors
    returnBrackets: function(competitors) {...},
    _filterWeightGroup: filterWeightGroup,
    _createBracketsByWeightGroup: createBracketsByWeightGroup