26

I'm trying to create some unit tests in Angular using Jasmine being run through Teaspoon. The tests are running, however I have a simple test just to test the existence of a controller that is failing. I have the following test setup.

//= require spec_helper

require("angular");
require("angular-mocks");
var app = require("./app");


describe("My App", function() {

  describe("App Controllers", function() {

    beforeEach(module("app"))

    it("Should have created an application controller", inject(function($rootScope, $controller){
      var scope = $rootScope.$new();
      ctrl = $controller("ApplicationCtrl", { $scope: scope });
    }));

  })

})

The require statements are processed by Browserify which is handling my dependencies, but I can also hook into sprockets which I'm using for the spec helper.

Inside the app that is being required, I have

require("angular");
var controllers = require("./controllers");

var app = angular.module("app", [
  "app.controllers"
]);

exports.app = app;

When I run this test, I get the following error produced

Failure/Error: TypeError: '[object Object]' is not a function (evaluating 'module("aialerts")')

I've spent quite a while trying to figure this out but I have no idea what's going on. Any help appreciated.

phoet
  • 18,688
  • 4
  • 46
  • 74
PaReeOhNos
  • 4,338
  • 3
  • 30
  • 41
  • Is `var app = require("./app");` loading the angular `app` module? – dcodesmith Jan 07 '14 at 10:03
  • Yeah. I've just posted the contents of that file :) – PaReeOhNos Jan 07 '14 at 10:09
  • I have no idea about browserify and that kind of weird stuff. But there is no need to load your app in the test that way (well, under my little experience with browserify). What happens with the require out? – Jesus Rodriguez Jan 07 '14 at 11:09
  • Exact same issue. Why don't I have to load my app? Surely I need the app loaded in order for it to have created the controller for me to test? I know I could directly load the controller for testing that, but I just want to test the existence of the controller within the application – PaReeOhNos Jan 07 '14 at 12:26
  • Hi @phoet, If I have answered your question could you please accept the answer? Thanks mate! – zayquan Oct 02 '14 at 21:32
  • Hi @zayquan that was not my question... – phoet Oct 02 '14 at 23:51
  • Also - remember in install angular-mocks... – bwobbones Aug 29 '17 at 14:39

2 Answers2

83

I had the same problem. Change this line:

beforeEach(module("app"))

to:

beforeEach(angular.mock.module("app"))
zayquan
  • 7,544
  • 2
  • 30
  • 39
  • 1
    angular.mock.module is enough, no need to put window before it – Capaj Oct 01 '14 at 14:37
  • Haven't been able to test this as I changed jobs but I'll assume it's right and works – PaReeOhNos Oct 03 '14 at 09:54
  • 1
    Adding `window` prefix is not going to work if you are using strict mode in your tests. Like others said, just prefix it with `angular.mock`. – demisx Jan 27 '15 at 16:42
  • @Dunc : link removed – zayquan Sep 13 '15 at 16:08
  • 2
    @DevAno1 both angular and Browserify declare the variable "module" , angular's is a funtion, I beleive Browserify's is an object. In any case you need to explicitly call "angular.mock.module" so that you use the correct one. HTH – zayquan Feb 27 '16 at 03:30
24

Browserify uses Node-style require, where module is an object that you can use to export functionality:

console.log(module); // {exports: {}}

angular-mocks.js tries to attach a function to window.module, but that's not possible in Browserify/Node.

Taking a look through the angular-mocks source, it appears that angular-mocks also attaches the module function to angular.mock. So instead of using the global module object, you must use angular.mock.module.

yndolok
  • 5,197
  • 2
  • 42
  • 46