Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting error when trying to use $provide in jasmine unit test

I'm using AngularJS and trying to test a controller that calls a factory to get some data.

This is the controller code:

'use strict'

angular.module('AngularApp')
  .controller 'IndexCtrl', ($scope, session, navigation) ->
    session.find().then (response) ->
      $scope.session = response.data

    $scope.someOtherVariable = {}

Naturally, I'd like to swap the factory with a mock to prevent calling a real API. I'm trying to use $provide.factory to inject the mock copy:

'use strict'

describe 'Controller: IndexCtrl', ->

  # load the controller's module
  beforeEach module 'mosaicAdminWebClientApp'
  beforeEach module ($provide) ->
    $provide.factory 'session', ->
      true

  IndexCtrl = {}
  scope = {}

  # Initialize the controller and a mock scope
  beforeEach inject ($controller, $rootScope) ->
    scope = $rootScope.$new()
    IndexCtrl = $controller 'IndexCtrl', {
      $scope: scope
    }

  it 'should attach a list of awesomeThings to the scope', ->
    expect(true).toBe true

When running this test with Karma, I guess this error:

Chrome 32.0.1700 (Mac OS X 10.9.1) Controller: IndexCtrl should attach a list of awesomeThings to the scope FAILED
    Error: [ng:areq] Argument 'fn' is not a function, got Object
    http://errors.angularjs.org/1.2.10-build.2176+sha.e020916/ng/areq?p0=fn&p1=not%20a%20function%2C%20got%20Object
        at /Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:78:12
        at assertArg (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:1363:11)
        at assertArgFn (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:1373:3)
        at annotate (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:3019:5)
        at Object.invoke (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:3685:21)
        at /Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:3554:71
        at Array.forEach (native)
        at forEach (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:303:11)
        at Object.createInjector [as injector] (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular/angular.js:3554:3)
        at workFn (/Users/blaiz/Documents/some_angular_app/app/bower_components/angular-mocks/angular-mocks.js:2144:52)
Chrome 32.0.1700 (Mac OS X 10.9.1): Executed 10 of 10 (1 FAILED) (0.26 secs / 0.068 secs)
Warning: Task "karma:unit" failed. Use --force to continue.

Aborted due to warnings.

I've tried many different permutation, such as removing the label, passing an object or simple value instead of a function and none of them worked.

The documentation (http://docs.angularjs.org/api/AUTO.$provide) shows that I should call the factory() method with as factory(name, $getFn) where name is a string and $getFn is a function. That's what I'm doing but it's not working.

Anything I've missed? Does anyone know how to properly use $provide in Jasmine unit tests?

Thanks

Update: I found a plunkr similar that solved an issue similar to this one here: stackoverflow.com/questions/19297258/why-is-provide-only-available-in-the-angular-mock-module-function-and-q-onl

I created my own plunkr with this code, but with the test code in JS instead of Coffee and got it to work: plnkr.co/edit/gfBzMXpKdJgPKnoyJy5A?p=preview

Now I manually converted the JS code into Coffee: plnkr.co/edit/qGGMayFjJoeYZyFKPjuR?p=preview The error is back so the coffee code is wrong but the js code works.

like image 225
Blaiz Avatar asked Jan 23 '14 02:01

Blaiz


1 Answers

Found the answer to my question.

Since CoffeeScript always returns the result from the last statement, in this case, CoffeeScript returns $provide inside of module(), which is wrong. An easy way to fix that is to just manually add a return statement after $provide, like this:

  beforeEach module 'mosaicAdminWebClientApp', ($provide) ->
    $provide.service 'session', ()->
    return

Hope that will help someone else.

like image 150
Blaiz Avatar answered Sep 28 '22 04:09

Blaiz