So I’m new to the whole testing thing (I’ve been one of those people who has said ‘I should write unit tests…’ but never ended up ever doing it :-p). I’m now writing unit tests for this project. I’m using testacular + Jasmine, with browserify to compile things. I was having no problems until I started trying to do a lot AngularJS injection-stuff.
Right now I’m simply trying to do a test of ng-model to get my head around all of it.
I have a testacular.conf file which includes everything necessary:
files = [ '../lib/jquery.js', '../lib/angular.js', './lib/jasmine.js', './lib/angular-mocks.js', JASMINE_ADAPTER, './tests.js' //compiled by browserify ];
I have my controller defined (MainCtrl.coffee)
MainCtrl = ($scope, $rootScope) -> $scope.hello = 'initial' module.exports = (angularModule) -> angularModule.controller 'MainCtrl', ['$scope', '$rootScope', MainCtrl] return MainCtrl
And I have my test itself: (_MainCtrlTest.coffee, in same directory as MainCtrl.coffee)
testModule = angular.module 'MainCtrlTest',  MainCtrl = require('./MainCtrl')(testModule) describe 'MainCtrlTest', -> scope = null elm = null ctrl = null beforeEach inject ($rootScope, $compile, $controller) -> scope = $rootScope.$new() ctrl = $controller MainCtrl, $scope: scope elm = $compile('<input ng-model="hello"/>')(scope) describe 'value $scope.hello', -> it 'should initially equal input value', -> expect(elm.val()).toBe scope.hello it 'should change when input value changes', -> scope.$apply -> elm.val('changedValue') expect(scope.hello).toBe elm.val()
The test fails immediately, with the input’s elm.val() returning blank, and scope.hello returning the intended value (‘initial’, set in MainCtrl.coffee)
What am I doing wrong here?
To get this working, you need to do
it 'should initially equal input value', -> scope.$apply() expect(elm.val()).toBe scope.hello
Don’t test the framework, test your code
Your test is trying to test whether Angular’s binding, and
ng-model works. You should rather trust the framework and test your code instead.
Your code is:
- the controller (setting initial
- html templates (and all the binding, directives in there)
You can test the first one very easily, without even touching any DOM. That’s the beauty of AngularJS – strong separation of view/logic.
In this controller, there is almost nothing to test, but the initial value:
it 'should init hello', -> expect(scope.hello).toBe 'initial'
To test the second one (template + binding), you want to do an e2e test. You basically want to test, whether the template doesn’t contain any typos in binding etc… So you wanna test the real template. If you inline a different html during the test, you are testing nothing but AngularJS.