Search code examples
angularjsnode.jsjasminebrowserify

Testing angular service that is also a promise


I'm working with browserify to bundle up an angular service. I'm using jasmine to write tests for this service, which is defined like:

angular
  .module('Client', [])
  .factory('client', ['url', 'otherService', '$http', '$log', client])

function client (url, otherService, $http, $log) {
  $log.debug('Creating for url %s', url)
  var apiRootPromise = $http.get(url).then(function (apiRoot) {
    $log.debug('Got api root %j', apiRoot)
    return otherService.stuff(apiRoot.data)
  })
  return Object.assign(apiRootPromise, otherService)
}

The following test suite:

describe('test client', function () {
    beforeEach(function () {
      angular.mock.module('Client')
      angular.mock.module(function ($provide) {
        $provide.value('url', 'http://localhost:8080/')
      })
    })

    it('should connect at startup', angular.mock.inject(function (client, $rootScope, $httpBackend) {
      $rootScope.$apply()
      $httpBackend.flush()
      expect(client).toBeDefined()
    }))
  })

Throws a TypeError: undefined is not a constructor on (evaluating Object.assign(apiRootPromise, otherService)'). I'm not sure what's happening here, but my best guess is Angular is not injecting properly the dependent service or not returning the $http promise.


Solution

  • Possible duplicate question

    Object.assign is introduced in ECMAScript 6th edition and is not currently natively supported in all browsers. Try using a polyfill for Object.assign. Here's one:

        if (typeof Object.assign != 'function') {
      (function () {
        Object.assign = function (target) {
          'use strict';
          if (target === undefined || target === null) {
            throw new TypeError('Cannot convert undefined or null to object');
          }
    
          var output = Object(target);
          for (var index = 1; index < arguments.length; index++) {
            var source = arguments[index];
            if (source !== undefined && source !== null) {
              for (var nextKey in source) {
                if (source.hasOwnProperty(nextKey)) {
                  output[nextKey] = source[nextKey];
                }
              }
            }
          }
          return output;
        };
      })();
    }
    

    Otherwise, your code is working in this fiddle (I had to fill in a few blanks, but the general gist is there)