0

I'm a complete rookie when it comes to unit testing with Jasmine and unit testing in general. My recent task has me trying to unit test an AngularJS controller. Below you'll see my code and what I've tried and most of it has failed to get me where I need to go. Any help would be appreciated!!

Controller

 angular
       .module('TDE')
       .controller('LocationController', ['$rootScope', '$scope', '$location', '$window', '$document', 'LocationService', 'HeaderFooterService', 'SearchService', 'TranslationService', 'MTDE_CONFIG', 'LocationPartnerAssignmentService', 'ExperimentService', function ($rootScope, $scope, $location, $window, $document, $LocationService, $HeaderFooterService, $SearchService, $TranslationService, $MTDE_CONFIG, $LocationPartnerAssignmentService, $ExperimentService) {

       //some non important code
       //What I'm trying to test
       $scope.boolTest= function(var){
          return true; //this method only returns true
       }
       //all I'm after is basic understanding, I've done countless searches but I can't get it

  //other code

Helper File (Test File)

beforeEach(function () {
        angular.mock.module('LocationController'); //
        inject(function ($injector) {
            //$rootScope = $injector.get('$rootScope');
            //$scope = $rootScope.$new();
            //ctrl = $injector.get('$controller')("LocationController", { $scope: $scope });
            //Neither ctrl really functions that well

            injector = $injector;
            ctrl = $injector.get('$controller');
            scope = $injector.get('$rootScope').$new();
        });
    });

Spec.html

<!-- jasmine source -->
    <link rel="shortcut icon" type="image/png" href="spec/lib/jasmine-1.2.0/jasmine_favicon.png">
    <link rel="stylesheet" type="text/css" href="spec/lib/jasmine-1.2.0/jasmine.css">
    <script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine.js"></script>
    <script type="text/javascript" src="spec/lib/jasmine-1.2.0/jasmine-html.js"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/1.1.0/angular-mocks.js"></script>

    <!-- include source files here... -->
    <script type="text/javascript" src="js/Location/LocationController.js"></script>
    <!-- include spec files here... -->
    <script type="text/javascript" src="spec/RTHelper.js"></script>

As of right now I am stuck, I can get really basic tests to work like a + b and verify the result, however I can not gain (at least I think) access to the $scope like I need for that method.

Current Error is No module: LocationController

I've tried it by using 'TDE' but nothing, someone please help me!

1 Answer 1

1

Sorry for the previous link, I didn't quite understand your problem there.

If you are setting up unit tests, I recommend you check Karma (http://karma-runner.github.io/0.12/index.html) which is the easiest way to test Angular code and integrate in a CI environment.

Anyway, here's an example of testing a basic controller in Jasmine:

function MyControllerCtrl ($scope, Service) {
  $scope.something = true;
  $scope.set = Service.set;
};

describe('MyControllerCtrl', function () {

  // load the controller's module using angular.mock.module
  beforeEach(module('myApp'));

  var subject
    , $scope
    , Service = { // mock the Service service
        set: function () {},
      }
    ;

  beforeEach(inject(function ($controller, $rootScope) {
    $scope = $rootScope.$new(); // create a new clean scope
    subject = $controller('MyControllerCtrl', {
      Service: Service,
      $scope: $scope,
    });

  }));

  it('should do something', function () {
    expect($scope.something).toEqual(true);
  });

  it('bind Service.set', function () {
    expect($scope.set).toEqual(Service.set);
  });

});

The idea behind this is that before each test, you pass the controller your mocked services ($scope is nothing but a service), then you test that the controller does what it has to do.

In your case, you can expect($scope.boolTest()).toEqual(true);

Sign up to request clarification or add additional context in comments.

5 Comments

The problem is though that for some reason it doesn't want to acknowledge any of my code in the Controller. I've tried all of the beforeEach(module('stuff')) combinations. It just doesn't seem to allow me to get going. I'm pretty sure it isn't a path issue as I've put other files I know work there and it fires fine. Whenever I try $controller('LocationController', {$scope: $rootScope}) it also fails and said "Error: Argument 'LocationController' is not a function, got undefined" you have any other ideas?
just verified that the file does load, the error reads as this Uncaught Error: No module: TDE
If you use module declaration in separate files, make sure you load these before your services and controllers definition, ie: file1.js angular.module('TDE', []); file2.js angular.module('TDE').controller('LocationController', function ...) Then in your test, you would have to mock the TDE module before injecting any of its dependencies to be stubbed: beforeEach(module('TDE')); beforeEach(inject(function ($controller) { subject = $controller('LocationController', { /* dependencies */ }) }));
Don't forget module creation: angular.module('myModule', [ /* dependencies */ ]); VS retrieval: angular.module('myModule').service(...).controller(...);
thanks for the help DrDyne, you pointed me the write way and I thank you! Unfortunately, I didn't write any of the code I'm testing here (perks of an intern) so it's been hunting! Thanks for the pointers!! Saved me many headaches and gray hairs!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.