Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing dependency injection

I am brand new to jasmine and karma. I believe I have the environment setup properly and I am able to run very basic unit tests, but as soon as I try to instantiate a controller I am given an unknown provider error and I am unsure how to debug this. Do I need to pass in a stateProvider dependency? I don't see this in the angular-seed example.

Bower.json:

{
"name": "starter",
  "description": "A starter project for AngularJS",
  "version": "2.0.0",
  "homepage": "https://starter.com",
  "private": true,
  "dependencies": {
      "angular": "1.2.x",
      "angular-route": "1.2.x",
      "angular-loader": "1.2.x",
      "angular-mocks": "~1.2.15"
  }
}

Home Controller:

angular.module('home').controller('Home', function($scope, $rootScope, $state) {

    console.log($scope.pageType);

    $rootScope.pageType = 'home';

    /*
     * Takes in a state and transitions the app to that state.
     */
    $scope.goTo = function(value) {
        $state.transitionTo(value);
    }

    /*
     * Handles what happens after clicking log-in
     */
    $scope.loginClicked = function() {
        $state.transitionTo('log-in');
    }
});

Test file:

'use strict';

/* jasmine specs for controllers go here */

describe('Home', function() {
    beforeEach(module('home'));

    it('should run tests', inject(function() {
        expect(null).toBeDefined();
    }));

    it('should not say true equals false', function() {
        expect(false).not.toBe(true);
    });

    it('should say true equals true', function() {
        expect(true).toBe(true);
    });

    it('should say false does not equal true', function() {
        expect(false).not.toBe(true);
    });

    it('should create "phones" model with 3 phones', inject(function($controller,$rootScope) {

    /*
     * 
     * COMMENTING OUT THESE LINES = PASS
     *
     */
        var scope = $rootScope.$new(),
            ctrl = $controller('Home', {$scope:scope});
        expect(ctrl).not.toBe(null);
    }));

});

Error:

    Error: [$injector:unpr] Unknown provider: $stateProvider <- $state
http://errors.angularjs.org/1.2.16/$injector/unpr?p0=%24stateProvider%20%3C-%20%24state
    at /Users/jlett/bower_components/angular/angular.js:78:12
    at /Users/jlett/bower_components/angular/angular.js:3705:19
    at Object.getService [as get] (/Users/jlett/bower_components/angular/angular.js:3832:39)
    at /Users/jlett/bower_components/angular/angular.js:3710:45
    at getService (/Users/jlett/bower_components/angular/angular.js:3832:39)
    at invoke (/Users/jlett/bower_components/angular/angular.js:3859:13)
    at Object.instantiate (/Users/jlett/bower_components/angular/angular.js:3880:23)
    at /Users/jlett/bower_components/angular/angular.js:7134:28
    at null.<anonymous> (/Users/jlett/test/unit/home-controller_tests.js:26:20)
    at Object.invoke (/Users/jlett/bower_components/angular/angular.js:3869:17)
Error: Declaration Location
    at window.inject.angular.mock.inject (/Users/jlett/bower_components/angular-mocks/angular-mocks.js:2132:25)
    at null.<anonymous> (/Users/jlett/test/unit/home-controller_tests.js:24:54)
    at /Users/jlett/zoetis-rimadyl-mobile/test/unit/home-controller_tests.js:5:1
like image 676
jeffctown Avatar asked Apr 23 '14 19:04

jeffctown


People also ask

Is dependency injection required for unit testing?

Unit testing is challenging when you add frameworks around your tests subjects. Dependency injection is one of those patterns supported by frameworks, that we usually need in any project.

Why is dependency injection useful for testing?

Dependency injection helps to develop testable code, allowing developers to write unit tests easily. You can use mock databases with dependency injection, and test your application without affecting the actual database.

What is unit testing and TDD?

TDD is a broader concept than unit tests. TDD is a software development approach focused on understanding the problem domain and fulfilling the requirements. Bare unit tests are about validating the written source code and avoiding bugs and regression. In fact, unit tests are part of the TDD cycle.

What is a unit test in Agile?

A unit test, as Agile teams understand the term, is a short program fragment written and maintained by the developers on the product team, which exercises some narrow part of the product's source code and checks the results.


1 Answers

You'll get this error if one of the injectables module isn't included.

For instance, you have

beforeEach(module('home'));

If your $state dependency is not in the home module, you'll need to include that module also. I'm not familiar with $state (I think it's angular-ui's router? Only angular.js services are supposed to start with $). If it's angular ui, this is how you should setup:

beforeEach(module('ui.router'));
beforeEach(module('home'));

This way, angular's test runner knows what modules are required to run your tests.

Really, the inclusion of the home module should do this for you as long as you have the ui.router dependency defined as a dependency of that module. If you have that configured correctly, you may need to look at the order of your files being included for your tests. For example, make sure the ui-router file is being included for your tests and that it is referenced before your home module in karma's config.

like image 166
Jim Schubert Avatar answered Sep 21 '22 23:09

Jim Schubert