angularjs - Unit testing function, how to implement call to mock object -
i'm writing unit tests controller has angular scope function when called, calls parse.com framework function makes call parse server , returns success parameters or error code.
how go making mock of object unit test?
the name of function in controller's scope parse.user.login, , here mock object i've made far.
mockparse = { user: { login: function(_username, _password, callbackobj) { callbackobj.success({ attributes:{ username: "testuser", email: "testuser@example.com" } $rootscope.user = _user; $rootscope.isloggedin = true; $state.go('tab.home'); }; callbackobj.error({ err:{ code: 101 } if (err.code == 101){ $scope.error.message = "invalid login credentials"; } else { $scope.error.message = "unexpected error" } }); } } }
did right? have make different objects different callback responses, error , success?
when put in test, inject it? place in controller, this?:
ctrl = $controller("loginctrl", { $scope: $scope, parse: mockparse });
here's actual function:
parse.user.login(($scope.user.username) , $scope.user.password, { success: function(_user) { console.log('login success'); console.log('user = ' + _user.attributes.username); console.log('email = ' + _user.attributes.email); $ionicloading.hide(); $rootscope.user = _user; $rootscope.isloggedin = true; $state.go('tab.home'); }, error: function(user, err) { $ionicloading.hide(); // login failed. check error see why. if (err.code === 101) { $scope.error.message = 'invalid login credentials'; } else { $scope.error.message = 'an unexpected error has ' + 'occurred, please try again.'; } console.log('error message on parse.user.login: ' + $scope.error.message); $scope.$apply(); } });
preface: not versed parse.js (nor jasmine matter)
i recommend go , grab sinonjs - super effective , (after time) easy use mocking/stubbing/spying.
start off not worrying internal implementation of parse
object, we're interested in input
, output
of our dependencies when in unit testing setting. there should no reason stub out service object in fine grade detail.
beforeeach
var $scope, parse, createcontroller; beforeeach(function () { parse = {}; module('your_module', function ($provide) { // provide "parse" value in module. $provide.value('parse', parse); }); inject(function ($controller, $injector) { $scope = $injector.get('$rootscope').$new(); parse = $injector.get('parse'); // equal to: {} (at point) createcontroller = function () { return $controller('loginctrl', { $scope: $scope, parse: parse }); }; }); parse.user = {}; parse.user.login = sinon.stub(); });
parse entirely stubbed out. empty object provided module, exposed in our spec, injected our controller , decorated stubbed out methods matching of actual implementation (only name, of course).
expectation(s)
what should testing in controller spec, not internal behaviour of parse
service, rather controller calling methods of parse
correct parameters.
after that, can go on test your controller, , its associated $scope in reaction parse.user.login()
response.
it's
note: writing these specs mocha/chai syntax - adopt jasmine style see fit (not sure how plays sinon.js quite honest)
it('calls parse method', function () { createcontroller(); $scope.login('username', 'pw', angular.noop); expect(parse.user.login).to.have .been.calledonce.and.calledwith('username', 'pw', angular.noop); }); context('parse response', function () { it('failed', function () { parse.user.login.returns({ status: 'super_error' }); createcontroller(); $scope.login('a', 'b', angular.noop); expect(/* expect on $scope happened? */); }); it('was succesful', function () { parse.user.login.returns({ status: 'great_success', data: {} }); createcontroller(); $scope.login('a', 'b', angular.noop); expect(/* expect on $scope happened? */); }); });
that how write it. - looking @ parse.user.login docs can see method returns promise
.
as such, need take following steps stub out correct behaviour:
var $q; // combine beforeeach block first 1 wrote. beforeeach(function () { inject(function ($injector) { $q = $injector.get('$q'); }); }); context('parse.user.login', inject(function ($timeout) { var success, error, opts; beforeeach(function () { success = sinon.stub(); error = sinon.stub(); opts = { success: success, error: error }; }); it('failed', function () { parse.user.login.returns($q.reject({ status: 'bad_error' }); createcontroller(); $scope.login('a', 'b', opts); $timeout.flush(); // either this, or $rootscope.$digest or .notify(done) flush promise. expect(error).to.have.been.calledonce; }); it('was successful', function () { parse.user.login.returns($q.when({ status: 'yay!', data: {} }); createcontroller(); $scope.login('a', 'b', opts); $timeout.flush(); // either this, or $rootscope.$digest or .notify(done) flush promise. expect(success).to.have.been.calledonce; }); }));
Comments
Post a Comment