我有一个角度服务班:
- angular.module('triggerTips')
- .service('userData',function ($rootScope,$http,$log,$firebase) {
- this._log = {
- service : 'userData'
- };
- // Synchronized objects storing the user data
- var config;
- var userState;
- // Loads the user data from firebase
- this.init = function(readyCallback) {
- var log = angular.extend({},this._log);
- log.funct = 'init';
- var fireRef = new Firebase('https://XYZfirebaseio.com/' + $rootScope.clientName);
- config = $firebase(fireRef.child('config')).$asObject();
- userState = $firebase(fireRef.child('userState').child($rootScope.userName)).$asObject();
- Promise.all([config.$loaded(),userState.$loaded()]).
- then(
- function() {
- if(config == null || Object.keys(config).length < 4) {
- log.message = 'Invalid config';
- $log.error(log);
- return;
- }
- if(!userState.userProperties) {
- userState.userProperties = {};
- }
- if(!userState.contentProperties) {
- userState.contentProperties = {};
- }
- log.message = 'User Properties: ' + JSON.stringify(userState.userProperties);
- $log.debug(log);
- log.message = 'Content Properties: ' + JSON.stringify(userState.contentProperties);
- $log.debug(log);
- log.message = 'Loaded user data from firebase';
- $log.debug(log);
- readyCallback();
- },function() {
- log.message = 'Unable to load user data from firebase';
- $log.error(log);
- }
- );
- };
- // Returns the initial tip configuration
- this.getConfig = function() {
- return config;
- };
- // Set the value of a user property
- // A user property is something about the user himself
- this.setUserProperty = function(property,value) {
- if(!userState.userProperties) {
- userState.userProperties = {};
- }
- userState.userProperties[property] = value;
- userState.$save();
- $rootScope.$broadcast('user-property-change',property);
- };
- // Get the value of a user property
- this.getUserProperty = function(property) {
- if(userState.userProperties) {
- return userState.userProperties[property];
- }
- };
- // Set the value of a user content property
- // A content property is something about a particular peice of content for a particular user
- this.setContentProperty = function(contentName,property,value) {
- if(!userState.contentProperties[contentName]) {
- userState.contentProperties[contentName] = {};
- }
- userState.contentProperties[contentName][property] = value;
- userState.$save();
- $rootScope.$broadcast('content-property-change',contentName,property);
- };
- // Increment a count property on the user state for a given tip
- this.incrementContentProperty = function(contentName,property) {
- if(!userState.contentProperties[contentName]) {
- userState.contentProperties[contentName] = {};
- }
- if(!userState.contentProperties[contentName][property]) {
- userState.contentProperties[contentName][property] = 0;
- }
- userState.contentProperties[contentName][property]++;
- userState.$save();
- $rootScope.$broadcast('content-property-change',property);
- };
- // Returns the user state for a given tip and property
- this.getContentProperty = function(contentName,property) {
- if(userState.contentProperties) {
- var t = userState.contentProperties[contentName];
- if(t) {
- return t[property];
- }
- }
- };
- });
我试图用茉莉花单元测试这个服务:
我的单位测试是:
- 'use strict';
- describe('Service: userData',function () {
- // load the service's module
- beforeEach(function() {
- module('triggerTips');
- });
- // instantiate service
- var userData;
- beforeEach(inject(function (_userData_) {
- userData = _userData_;
- }));
- it('should load correctly',function () {
- expect(!!userData).toBe(true);
- });
- describe('after being initialized',function () {
- beforeEach(function(done) {
- // Unable to get this working because the callback is never called
- userData.init(function() {
- done();
- });
- jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;
- });
- it('should have a valid config',function (done) {
- setTimeout(function() {
- expect(Object.keys(userData.getConfig()).length == 0);
- done();
- },1500);}); }); });
我阅读了关于Jasmine的异步支持,但是由于我相当新的使用JavaScript的单元测试无法使其工作.
我收到一个错误:
Async callback was not invoked within timeout specified by
jasmine.DEFAULT_TIMEOUT_INTERVAL
有人可以帮我提供我的代码的工作示例一些解释吗?
我建议您用$timeout替换setTimeout,以加快您的规格套件.您将需要
ngMock作为您的规格套件的一部分,以使其以预期的方式工作,但这似乎已被照顾您的规格.好东西.
那么为了使规范的异步性质“走开”,你会呼吁:
$timeout.flush([delay])其中延迟是可选的.
>如果没有延迟通过,所有待处理的异步任务(有角度的世界)将完成他们在做什么.
>如果传递延迟,则指定延迟内的所有待处理任务将完成.指定延迟之外的人将保持在“待定”状态.
这样,您可以删除完成的回调并编写您的测试:
- describe('after being initialized',function () {
- var $timeout;
- beforeEach(function () {
- // Unable to get this working because the callback is never called
- userData.init();
- inject(function ($injector) {
- $timeout = $injector.get('$timeout');
- });
- }));
- it('should have a valid config',function () {
- $timeout.flush();
- // callback should've been called now that we flushed().
- expect(Object.keys(userData.getConfig()).length).toEqual(0);
- });
- });
你使用什么承诺?我看到Promise.all的电话,但是为了继续我的答案,我将假设它相当于$q.all.运行$timeout.flush应该处理这些值.
如果你想对茉莉花的承诺的拒绝/解决的价值写出期望,我会研究一下像jasmine-promise-matchers这样的东西,使它干净漂亮,但是禁止你这样做:
- // $q
- function get () {
- var p1 = $timeout(function () { return 'x'; },250);
- var p2 = $timeout(function () { return 'y'; },2500);
- return $q.all([p1,p2]);
- }
- // expectation
- it('is correct',function () {
- var res;
- get().then(function (r) {
- res = r;
- });
- $timeout.flush(2500);
- expect(res).toEqual(['x','y']);
- });
根据您的设置,您可能需要或可能不需要根据您的本地配置变量存储/监视(取决于您的框架定义的间谍)承诺,但这是我估计的另一个故事.
我不熟悉$firebase(某事)$asObject.$loaded – 因此我可能错过了这里的东西,但假设它的工作原理就像任何其他承诺一样,你应该很好.