Angular-styleguide: Karma / Jasmin unit test problems

Created on 17 Feb 2016  Β·  53Comments  Β·  Source: johnpapa/angular-styleguide

Hi Johnpapa,

first of all let me thank you for this amazing guide (I really love it)!! Apologize for my awful english..
I am learning how to write test for the first time and I have some problems to use karma / jasmine test in a project of mine.

This is the controller

(function() {
  'use strict';

  angular
    .module('name-module')
    .controller('NameCtrl', NameCtrl);

  function NameCtrl(){

    var vm = this;

    vm.country = null;

 }
})();

and this is the spec file

describe('NameCtrl functionality', function() {

  beforeEach(module('name-module'));

  var $controller;

  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));

  describe('Test controller', function() {
    it('Verify if country is null', function() {

      var $scope = {};
      var vm = $controller('NameCtrl', { $scope: $scope });

      expect(vm.country).toBe(null);

    });
  });

});

The console log return me this:

TypeError: undefined is not a constructor (evaluating '$controller('NameCtrl', { $scope: $scope })')

What's wrong? (sorry for this issue, maybe is a silly request but I don't understand how to test with this styleguide)

Most helpful comment

Glad that you find the problem. :) I would be happy to contribute to your repo.

All 53 comments

You have to create the controller inside the beforeEach statement.

@bampakoa done, but still doesn't work

describe('vm.country', function() {
    var scope, vm;

    beforeEach(function() {
      scope = {};
      vm = $controller('NameCtrl', { $scope: scope });
    });

    it('verify if country is null', function() {
      expect(vm.country).toBe(null);
    });

});

In case you need to inject scope into your controller, you must create one from the rootScope:

  beforeEach(inject(function (_$rootScope_) {
         scope = _$rootScope_.$new();
          vm = $controller('NameCtrl', { $scope: scope });
        }));

@bampakoa at the moment, the only thing i want, is to test a controller and verify if the vm.country is null (then I'll implement more tests)

Could you test without injecting the scope?

@bampakoa how?

vm = $controller('NameCtrl');

@bampakoa now I have this spec file:

describe('CONTROLLER: NameCtrl', function() {

  beforeEach(module('module-name'));

  var $controller;

  beforeEach(inject(function(_$controller_){
    $controller = _$controller_;
  }));

  describe('Test controller', function() {
    it('Verify if country is null', function() {

      var vm = $controller('NameCtrl');

      expect(vm.country).toBe(null);

    });
  });

});

and this is the response:

TypeError: undefined is not a constructor

I tested your code as is and I get no error. What version of Jasmine/Karma/Angular do you use?

this is my package.json:

{
  "name": "my-grunt-angular-boilerplate",
  "version": "0.1.0",
  "description": "Custom grunt and angular.js boilerplate (to start projects)",
  "repository": {
    "type": "git",
    "url": "git+https://[email protected]/ibbatta/grunt-custom.git"
  },
  "scripts": {
    "start": "node bin/www 9003",
    "dev": "node bin/www 9001 /../app/",
    "test": "node_modules/karma/bin/karma start"
  },
  "keywords": [
    "grunt",
    "angular",
    "custom",
    "boilerplate",
    "project"
  ],
  "author": "Maurizio Battaghini",
  "license": "ISC",
  "homepage": "https://bitbucket.org/ibbatta/grunt-custom#readme",
  "devDependencies": {
    "angular-mocks": "^1.5.0",
    "autoprefixer": "^6.3.1",
    "grunt": "^0.4.5",
    "grunt-bower-concat": "^0.6.0",
    "grunt-bower-requirejs": "^2.0.0",
    "grunt-bower-task": "^0.4.0",
    "grunt-cli": "^0.1.13",
    "grunt-contrib-clean": "^0.7.0",
    "grunt-contrib-compress": "^0.14.0",
    "grunt-contrib-concat": "^0.5.1",
    "grunt-contrib-copy": "^0.8.2",
    "grunt-contrib-cssmin": "^0.14.0",
    "grunt-contrib-htmlmin": "^0.6.0",
    "grunt-contrib-jshint": "^0.12.0",
    "grunt-contrib-uglify": "^0.11.0",
    "grunt-contrib-watch": "^0.6.1",
    "grunt-express": "^1.4.1",
    "grunt-injector": "^0.6.1",
    "grunt-parallel": "^0.4.1",
    "grunt-postcss": "^0.7.1",
    "grunt-sass": "^1.1.0",
    "grunt-usemin": "^3.1.1",
    "grunt-wiredep": "^2.0.0",
    "jasmine-core": "^2.4.1",
    "jshint-stylish": "^2.1.0",
    "karma": "^0.13.21",
    "karma-chrome-launcher": "^0.2.2",
    "karma-coverage": "^0.5.3",
    "karma-firefox-launcher": "^0.1.7",
    "karma-ie-launcher": "^0.2.0",
    "karma-jasmine": "^0.3.7",
    "karma-ng-html2js-preprocessor": "^0.2.1",
    "karma-opera-launcher": "^0.3.0",
    "karma-phantomjs-launcher": "^1.0.0",
    "karma-safari-launcher": "^0.1.1",
    "load-grunt-tasks": "^3.4.0",
    "lodash": "^4.2.0",
    "phantomjs-prebuilt": "^2.1.4"
  },
  "dependencies": {
    "angular": "^1.5.0",
    "express": "^4.13.4",
    "request": "^2.69.0"
  }
}

maybe should be a karma.conf.js problem? or may the spec file have to be in the same root as controller? Should be a ui.route problems? controller alias? I really don't know how to resolve!

Please make sure that you load angular.js in the karma.conf file.

is this?

// list of files / patterns to load in the browser
    files: [
      'node_modules/angular/angular.js',
      'node_modules/angular-mocks/angular-mocks.js',
      'app/**/*.js',
      'test/**/*.spec.js'
    ],

In my case I also have:

'app/app.js',
'app/**/*.module.js',
'app/**/*.js',

where app.js is the main application file which contains module dependencies and module.js is the place that I define each module, if that helps you.

I have this structure:

/
β€” karma.conf.js
β€” package.json
β€” bower.json

β€” app/
β€”β€” index.js (_main app file_)
β€”β€”β€” templates/
β€”β€”β€”β€” controller.js (_the controller i've pasted before_)

β€” test/
β€”β€” folder/
β€”β€”β€” file.spec.js (_the spec file i've pasted before_)

with app/**/*.js i supposed to include all .js files, am I wrong?

Try to add index.js file before all the others such as :

'app/index.js',
'app/**/*.js'

in order to avoid initialization problems. Also I cannot find your module initialization. Something like:

(function () {
    'use strict';

    angular.module('module-name', []);
})();

Done.
Still show error

:(

Could you make a plunker with the source code of the index.js, controller.js and file.spec.js?

You also need to add ui-router, ui-bootstrap and toaster in the karma configuration file.

@bampakoa !? Why? If I import module without them the test dosn't work? Are necessaries? They are bower dependencies

They are needed because they are dependencies of module-name as stated in index.js:

    .module('module-name', [
        'ui.router',
        'ui.bootstrap',
        'toaster'
    ])

There is a fast way to import all modules in karma configuration file without write one by one?

You actually need to import only 3rd party (bower) modules one by one, not all your application modules that you have created. Nevertheless, I am not aware of such a way.

@bampakoa done with 'app/vendors/**/*.min.js'
Still return error :(

TypeError: undefined is not an object (evaluating 'vm.country')

I tried your code by importing them one by one and it worked.I have run out of ideas here. You could ask to SO or you could make a repository in GitHub so that I can download the sample and give you a hand.

@bampakoa ok man last try. Can you give me a hand to this repo?
https://github.com/ibbatta/angular-bootstrap-grunt-boilerplate

Actually I'm trying to create test for controllers (want to be a contributor? Sounds like a proposal ahahah)

@bampakoa OH SHIT MAN IT WORKS!! (i had to import bower modules manually and not with 'app/vendors/**/*.min.js'

Thanks a lot!!!!!!! <3
(anyway, if you want help me build test for my repo, you are welcome)

Glad that you find the problem. :) I would be happy to contribute to your repo.

thanx alot @bampakoa , I have this problem too, and your comment solved it ;)

@bampakoa thanks a lot. You saved my day

@bampakoa ΓΌber alles <3

@bampakoa thanks alot, after 5 hours of searching around the web, this was the final solution :)!

@MoschersMarco Glad I helped!

@bampakoa Thank you so much, was struggling with these problems for 3 days, and since there too many file on the project couldn't find it properly.
Keep up the good work.

@bampakoa Thank you so much!

@bampakoa Thanks man! this needs to be documented somewhere!

@kanish671 Thanks for the suggestion! Here is an article that I have written which describes how it was solved.

I am using this code

'use strict';

describe('app', function() {

beforeEach(angular.mock.module('app')); 

var $filter;

angular.mock.inject(function(_$filter_) {
    $filter = _$filter_;
});

it('should convert hours to minute', function($filter) {
  var hours = $filter('hoursToMinutes')(1);
  expect(hours).toBe(60);
});

});

but it showing me error

TypeError: null is not a constructor (evaluating '$filter('hoursToMinutes')(1)') in unit/AngularUnitTestSpec.js (line 37)
unit/AngularUnitTestSpec.js:37:44
loaded@http://localhost:9876/context.js:162:17

Can anyone help me on this?

This is my karma.conf.js

// Karma configuration
// Generated on Wed Jul 05 2017 23:14:03 GMT+0530 (India Standard Time)

module.exports = function(config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],

// list of files / patterns to load in the browser
files: [
  '../../../bower_components/angular/angular.js',
  '../../../bower_components/angular-animate/angular-animate.js',
  '../../../bower_components/angular-mocks/angular-mocks.js',      
  '../../../bower_components/angular-sanitize/angular-sanitize.js',
  '../../../bower_components/angular-bootstrap/ui-bootstrap.js',
  '../../../bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
  '../../../bower_components/angular-cookies/angular-cookies.js',
  '../../../bower_components/angular-validation-match/src/angular-validation-match.js',
  '../../../bower_components/ng-sortable/dist/ng-sortable.js',   
  '../app.js',
  '../filters.js',    
  'unit/*.js'
],

// list of files to exclude
exclude: [      
],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,


// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
//browsers: ['Chrome'],


// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity

})
}

This is my package.json

{
"name": "CMDBEditor",
"version": "2.4.25",
"description": "CMDB Editor",
"main": "server.js",
"author": "Varun Sondhi",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"angular-schema-form-dynamic-select": "^0.13.1",
"body-parser": "^1.4.3",
"express": "^4.13.4",
"express-http-proxy": "^0.7.1",
"forever-monitor": "^1.7.0",
"http-proxy": "^1.16.2",
"method-override": "^2.1.3",
"mongoose": "^4.4.12",
"morgan": "^1.1.1",
"multer": "1.1.0"
},
"devDependencies": {
"gulp": "^3.9.1",
"gulp-bump": "^2.7.0",
"gulp-clean": "^0.3.2",
"gulp-clean-css": "^3.3.1",
"gulp-concat": "^2.6.1",
"gulp-gzip": "^1.4.0",
"gulp-htmlmin": "^3.0.0",
"gulp-minify": "^1.0.0",
"gulp-minify-css": "^1.2.4",
"gulp-order": "^1.1.1",
"gulp-rename": "^1.2.2",
"gulp-sequence": "^0.4.6",
"gulp-tar": "^1.9.0",
"gulp-uglify": "^2.1.2",
"jasmine": "^2.6.0",
"karma": "^1.7.0",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.4"
},
"engines": {
"node": "4.4.3",
"npm": "2.15.1"
}
}

Please help me i m struggling on this issue last 2months but not able to rectify it.

@sanchitacool The best place to ask for these type of problems is on StackOverflow. By the way, you don't need $filter in the it statement.

I tried in stackflow but not getting any answer, anyways filter is required because in filter.js

app.filter('hoursToMinutes', function() {
return function(hours) {
return hours * 60;
};
});

how it take filter name?

@sanchitacool check this plnkr that I have set up for you. If you still have problems you can contact me via email.

Wrong Code

Hello @ all,

i have also this problem in angular 5: this is my service i will test:

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import * as _ from 'lodash';

import DarkSkyApi from 'dark-sky-api';
import {DarkSkyApiModel} from '../typing/wetterTypings';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import IDarkSkyApi = DarkSkyApiModel.Api.IDarkSkyApi;
import IDarkSkyForecastData = DarkSkyApiModel.Forecast.IDarkSkyForecastData;
import IDarkSkyCurrentData = DarkSkyApiModel.Current.IDarkSkyCurrentData;


@Injectable()
export class WetterService {

  private skyApi: IDarkSkyApi;

  /***
   * Konstruktor
   */
  constructor(private http: HttpClient) {
    this.skyApi = this.InitDarkSky();
  }

  /**
   * Die Verbindung zur API Darksky initalialisiern
   */
  private InitDarkSky(): IDarkSkyApi {
    const darksky: IDarkSkyApi = new DarkSkyApi(this.ApiKey);

    // Ansteuern der Api
    return darksky
      .units('si')
      .language('de');
  }

and this is my testfile:

import { TestBed, inject } from '@angular/core/testing';

import { WetterService } from './wetter.service';
import {HttpClientModule} from '@angular/common/http';
import DarkSkyApi from 'dark-sky-api';

describe('WetterService', () => {
  let darkSkyApi: DarkSkyApi;

  beforeEach(() => {
    darkSkyApi = new DarkSkyApi();
    TestBed.configureTestingModule({
      providers: [WetterService],
      imports: [HttpClientModule]
    });
  });

  it('should be created', inject([WetterService], (service: WetterService) => {
    expect(service).toBeTruthy();
  }));
});

i become this error:

TypeError: dark_sky_api_1.default is not a constructor in

@kaemmi84 This repository refers to AngularJS. It would be a good fit also to post your question on SO.

@johnpapa
Hi Johnpapa, i am new to angularjs unit testing using karma-jasmine with gulp,but now i got error while running gulp mytest

Chrome 63.0.3239 (Windows 10.0.0) Controllers My signUp-controller Should check the sssignUpController Controller to be defined FAILED
Error: [$injector:modulerr] http://errors.angularjs.org/1.4.8/$injector/modulerr?p0=nextStep&p1=Error%3A%20%5B%24injector%3Amodulerr%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.4.8%2F%24injector%2Fmodulerr%3Fp0%3Doc.lazyLoad%26p1%3DNo%2520module%2520found%2520during%2520bootstrap%252C%2520unable%2520to%2520init%2520ocLazyLoad%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A19%3A20%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A947%3A156%0A%20%20%20%20at%20n%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A35%3A62)%0A%20%20%20%20at%20g%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A931%3A13)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A945%3A57%0A%20%20%20%20at%20n%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A35%3A62)%0A%20%20%20%20at%20g%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A931%3A13)%0A%20%20%20%20at%20Object.eb%20%5Bas%20injector%5D%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular.min.js%3F630b8406b32181cef7898426f936bdbafbaecf2e%3A1024%3A11)%0A%20%20%20%20at%20UserContext.WorkFn%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Flib%2Fangular%2Fangular-mocks.js%3F0f959298566fbf2fae9f6691090bc0ac50bc5c68%3A3122%3A52)%0A%20%20%20%20at%20attempt%20(http%3A%2F%2Flocalhost%3A9876%2Fbase%2Fnode_modules%2Fjasmine-core%2Flib%2Fjasmine-core%2Fjasmine.js%3Fda85e4cfeaac0a6a0d0a4bb0d402ae04860be411%3A4440%3A46)
at lib/angular/angular.min.js:19:20
at lib/angular/angular.min.js:947:156
at n (lib/angular/angular.min.js:35:62)
at g (lib/angular/angular.min.js:931:13)
at Object.eb [as injector] (lib/angular/angular.min.js:1024:11)
at UserContext.WorkFn (lib/angular/angular-mocks.js:3122:52)
Chrome 63.0.3239 (Windows 10.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.026 secs / 0 secs)

can please anyone to help me?

@muniyappankalinathan It seems that nextStep module is not loaded in your karma test runner

@muniyappankalinathan a module (probably nextStep) failed to load/be injected correctly? Could you provide the relevant spec file?

How

@bampakoa OH SHIT MAN IT WORKS!! (i had to import bower modules manually and not with 'app/vendors/**/*.min.js'

Thanks a lot!!!!!!! <3
(anyway, if you want help me build test for my repo, you are welcome)

How to import the bower modules manually?

I am also facing similar issue TypeError: undefined is not a constructor (evaluating '$repoTraderController('PrimebrokerController')')?
I tried to import it manually like this
import {beforeEach, describe} from "selenium-webdriver/testing";
import * as $injector from "../../../bower_components/moment/src/lib/duration/get";
import inject from "../../../node_modules_new/acorn-dynamic-import/src/inject";

then i got this error .. SyntaxError: Use of reserved word 'import'.

Please help

@aaishna See this comment. It should be the same as node_modules

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Foxandxss picture Foxandxss  Β·  13Comments

sgbeal picture sgbeal  Β·  7Comments

samithaf picture samithaf  Β·  12Comments

alsfurlan picture alsfurlan  Β·  37Comments

robrothedev picture robrothedev  Β·  6Comments