Skip to content

Instantly share code, notes, and snippets.

@ksheedlo
Last active August 29, 2015 14:04
Show Gist options
  • Save ksheedlo/634e1bf8ad8751c0cc22 to your computer and use it in GitHub Desktop.
Save ksheedlo/634e1bf8ad8751c0cc22 to your computer and use it in GitHub Desktop.

The best place to start learning about how to test your Angular code is the Unit Testing section of the AngularJS Developer Guide. Some of the important takeaways from the guide are that

  • dependency injection is the best way to get ahold of dependencies for testing purposes. Angular has this built in, but you can help by not manipulating the DOM in your application (e.g., controller) logic.
  • use the $compile service to bind scope to a directive's DOM for testing

Some other helpful practices I've discovered through experience:

  • Directives often have their own controller. You can pull this controller out to make testing easier. For instance:

    function MyDirectiveCtrl($scope) {
      // Controller logic for the directive
    }
    angular.module('myApp').directive('myDirective', function () {
      return {
        // other DDO fields omitted for brevity
        controller: ['$scope', MyDirectiveCtrl]
      };
    });
  • You can use the $controller service to instantiate controllers, and $rootScope.$new() to create new Scopes, as in the following example:

    it('should test the directive controller', inject(function ($rootScope, $controller) {
      var scope = $rootScope.$new();
      
      // this runs the controller logic on the scope
      $controller('MyDirectiveCtrl', { $scope: scope });
      expect(scope.theAnswer).toBe('42');
    }));
  • Angular applications often gather resource data from REST or other HTTP APIs. The $httpBackend mock makes it easy to fake out these types of services for unit testing. Use it!

    describe('a resource', function () {
      var $httpBackend;
      
      beforeEach(module('myApp'));
      
      beforeEach(inject(function (_$httpBackend_) {
        $httpBackend = _$httpBackend_;
      }));
      
      afterEach(function () {
        $httpBackend.verifyNoOutstandingExpectation();
      });
      
      it('should expect HTTP requests and provide fake responses', inject(function ($rootScope, $controller) {
        $httpBackend.expectGET('/api/unicorns/9001')
          .respond({ name: 'Louie' });
         var scope = $rootScope.$new();
         $controller('GetThe9001stUnicornCtrl', { $scope: scope });
         
         // Important: HTTP request/responses must be flushed explicitly!
         $httpBackend.flush();
         expect(scope.unicorn.name).toBe('Louie');
      }));
    });
  • Use $httpBackend.expect() when the order of HTTP requests and responses matters and you only need one request at a time. Use $httpBackend.when() when you need to mock multiple requests.

https://docs.angularjs.org/guide/unit-testing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment