vendredi 6 février 2015

AngularJS + RequireJS + Karma Testing setup

I'm trying to set up Karma unit testing for an existing medium sized AngularJS + RequireJS application. I've hit a wall and everything I'm finding online is targeted at smaller applications that don't have as complicated of testing setups. I think I'm misunderstanding a crucial part of what happens before the test itself is run, and if someone could help point me in the right direction, it would be greatly appreciated.


The application runs fine so the RequireJS setup is correct. Testing seems to be setup correctly to the point where it loads all the files it needs (dependencies, application files, tests), and tries to run a test. The problem at that point is that my application files are not finding all the dependencies they need. I'll end up with an error like this:



Error: [$injector:unpr] Unknown provider: $resourceProvider <- $resource <- ClipboardResource <- ClipboardService


ClipboardService is a member of the app.clipboard module, and it's injected into what I'm actually trying to test - my MainController. MainController is of the app.common module. For clarity, both app.clipboard and app.common are required into the top level 'app' module. ClipboardService injects ClipboardResource and obviously ClipboardResource needs $resource and it's not finding it. Here's the test that's causing that error:



define([
'angular',
'angular-mocks',
'mock'
], function(angular, mocks, app) { // these are all defined, I checked!

describe('Controller: MainController', function() {

var scope, subject;

beforeEach(function() {

module('app.clipboard');
module('app.common');

inject(function($rootScope, $controller) {
scope = $rootScope.$new();
subject = $controller('MainController', {
$scope: scope
});
});
});

describe('check if controller is on it\'s place', function() {
it('should have loaded the subject', function() {
expect(subject).toBeDefined();
});
});

describe('check if scope is also on it\'s place', function() {
it('should test scope to be defined', function() {
expect(scope).toBeDefined();
});
});

});
});


Mock is pulling in all deps and bootstrapping the app, like so:



require([
/* Angular application deps */
'jquery',
'angular',
'angular-animate',
'angular-sanitize',
'angular-cookies',
'angular-resource',
'angular-route',
'angular-mocks',

'app.module' // loads all the other modules, including app.clipboard and app.common
], function($, angular) {
$(function() {
/** Only Angular deps and addons get passed into this */
var app = angular.bootstrap(document, [
'ngAnimate',
'ngSanitize',
'ngCookies',
'ngResource',
'ngRoute',
'ngMock',
'app'
]);
return app;
});
});


I suspect 'mock.js' is the culprit, but I don't know why. I'm confused why:


1) If I require 'mock' at the top of my test file, why isn't ngResource there when ClipboardResource tries inject it?


2) Why do I need to define modules in the beforeEach of my test?



module('app.clipboard');
module('app.common');


Shouldn't they already have been pulled in by mock.js since it's requiring app.module which kicks off the process of requiring in all application files?


I realize this is fairly abstract - I'm definitely working against the size of this application! Thanks in advance for any help.


Aucun commentaire:

Enregistrer un commentaire