Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular testing using passThrough in unit testing

I'm trying to test a Directive in Angular, but I can't get the corresponding template to work.

The directive lists the templateUrl like so

templateUrl: 'directives/listview/view.html'

Now when I write any unit-test, I get

Error: Unexpected request: GET directives/listview/view.html

So I have to use the $httpBackend and respond with something sensible like

httpBackend.whenGET('directives/listview/view.html').respond("<div>som</div>");

But really I want to simply return the actual file, and also do it synchronously, so there's no issues with waits, deferred objects etc. How to do that?

like image 609
Willem Mulder Avatar asked Oct 11 '13 14:10

Willem Mulder


People also ask

What does Angular use for unit testing?

Jasmine and Karma frameworks are used for Unit Testing of the Angular applications.

Which mentioned need Angular testing utilities for unit testing?

The correct answer is - Unit tests! Which of the following will need Angular testing utilities for unit testing? The correct answer is - Components!

What is SpyOn in Angular unit testing?

SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result.


2 Answers

I now use https://github.com/karma-runner/karma-ng-html2js-preprocessor. What it does is reading in all the templates that you use, convert them to Angular templates, and set them on the $templateCache, so when your app needs them, it will retrieve them from cache, and not request them from the server.

In my karma conf file

files: [
    // templates
    '../**/*.html'
],

preprocessors : {
  // generate js files from html templates
  '../**/*.html': 'ng-html2js'
},

ngHtml2JsPreprocessor: {
    // setting this option will create only a single module that contains templates
    // from all the files, so you can load them all with module('templates')
    moduleName: 'templates'
},

And then in the test, do like

// Load templates
angular.mock.module('templates');

And it works!

like image 69
Willem Mulder Avatar answered Sep 19 '22 14:09

Willem Mulder


Be sure to include the ngMockE2E module in your beforeEach

If you don't the $browser service mock will not be instantiated when whenGET is called, and the return value will not set up the passThrough function

beforeEach(function() {
   module('yourModule');
   module('ngMockE2E'); //<-- IMPORTANT!

   inject(function(_$httpBackend_) {
    $httpBackend = _$httpBackend_;
    $httpBackend.whenGET('somefile.html').passThrough();
   });
});

The place in angular-mocks.js where this is set up:

The source code in question is in $httpBackend mock's when function:

function (method, url, data, headers) {
  var definition = new MockHttpExpectation(method, url, data, headers),
      chain = {
        respond: function(status, data, headers) {
          definition.response = createResponse(status, data, headers);
        }
      };

  if ($browser) {
    chain.passThrough = function() {
      definition.passThrough = true;
    };
  }
  definitions.push(definition);
  return chain;
} 
like image 45
Ben Lesh Avatar answered Sep 20 '22 14:09

Ben Lesh