测试服务如何在AngularJS中使用IndexedDB

时间:2015-12-01 08:14:33

标签: javascript angularjs unit-testing jasmine indexeddb

我在AngularJS中有app,我在那里创建服务,将数据存储到IndexedDb。 它看起来像这样:

var IndexedDbServices = angular.module('IndexedDbServices', []);

IndexedDbServices.factory('IndexedDb', ['$window', '$q', function($window, $q){
    var indexedDB = $window.indexedDB;
    var db=null;

    var open = function() {
        var deferred = $q.defer();
        var version = 3;
        var request = indexedDB.open("lCApp", version);

        request.onupgradeneeded = function(e) {
            db = e.target.result;    
            e.target.transaction.onerror = indexedDB.onerror;

            if(db.objectStoreNames.contains("collections")) {
                db.deleteObjectStore("collections");
            }

            var store = db.createObjectStore("collections", {
                keyPath: "id", autoIncrement : true
            });
            store.createIndex("name", "name", { unique: true });
            store.createIndex("description", "description", { unique: false });

            store.transaction.oncomplete = function(event) {
                var customerObjectStore = db.transaction("collections", "readwrite").objectStore("collections");
                customerObjectStore.add({name: "coll1", description: "desc for coll1"});
                customerObjectStore.add({name: "coll2", description: "desc for coll2"});
            };    
        };

        request.onsuccess = function(e) {
            db = e.target.result;
            deferred.resolve();
        };

        request.onerror = function(){
            deferred.reject();
        };

        return deferred.promise;
    };


    var findAll = function() {
        var deferred = $q.defer();
        if(db === null || db === undefined) {
            deferred.reject("IndexDB is not opened yet!");
        } else{
            var trans = db.transaction(["collections"], "readwrite");
            var store = trans.objectStore("collections");
            var data = [];

            // Get everything in the store;
            var keyRange = IDBKeyRange.lowerBound(0);
            var cursorRequest = store.openCursor(keyRange);

            cursorRequest.onsuccess = function(e) {
                var result = e.target.result;
                if(result === null || result === undefined)
                {
                    deferred.resolve(data);
                }
                else{
                    data.push(result.value);
                    result.continue();
                }
            };

            cursorRequest.onerror = function(e){
                console.log(e.value);
                deferred.reject("Something went wrong!!!");
            };
        }

        return deferred.promise;
    };

    return {
        open: open,
        add: add,
        findAll: findAll
    };
}]);

我想用单元测试(jasmine)测试这段代码。所以我写了这个:

describe('IndexedDB service', function() {
    beforeEach(function() {
      module('IndexedDbServices');
    });

    it('should open db and find 2 collections', inject(function(IndexedDb) {
      IndexedDb.open().then(function(e){
        console.log(e);
      }, function(err){
        $window.alert(err);
      });

      console.log(IndexedDb.findAll());
  }));
});

您是否建议我如何在IndexedDb服务中打开函数创建IndexedDb并添加行。接下来我在IndexedDB服务中打开函数返回所有那些记录?

我不知道为什么,但在这个测试中没有创建db

console.log(IndexedDb.findAll());
print:Promise {$$ state:Object {status:2,value:'IndexDB尚未打开! “}} 所以不创建Db。 接下来如何在返回的promise中使用expect(..)。toEqual()或其他东西?

1 个答案:

答案 0 :(得分:0)

我们有服务:

/*global window: false */
'use strict';

angular.module('main')
  .config(['$provide', function ($provide) {
    $provide.constant('indexedDB', window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
  }])
  .service('idb', function idbService($q, $rootScope, indexedDB) {
    var service = this;
    var db;

    service.open = function () {
      console.log('idb.open');
      var deferred = $q.defer();
      var request = indexedDB.open('mydb', 1);
      request.onupgradeneeded = function (e) {
        console.log('idb.open onupgradeneeded');
        db = e.target.result;
        if (!db.objectStoreNames.contains('mystore')) {
          db.createObjectStore('mystore', {
            keyPath: 'id'
          });
        }
      };
      request.onsuccess = function (e) {
        console.log('idb.open onsuccess');
        db = e.target.result;
        deferred.resolve();
        $rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
      };
      request.onerror = function (e) {
        console.log('idb.open onerror ', e);
        deferred.reject();
      };
      return deferred.promise;
    };

    service.put = function (key, value) {
      console.log('idb.put(' + key + ', ' + value + ')');
      var deferred = $q.defer();
      var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
      var request = store.put({
        id: key,
        data: value
      });
      request.onsuccess = function () {
        console.log('idb.put onsuccess');
        deferred.resolve();
        $rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
      };
      request.onerror = function (e) {
        console.log('idb.put onerror ', e);
        deferred.reject(e);
      };
      return deferred.promise;
    };

    service.get = function (key) {
      console.log('idb.get' + '(' + key + ')');
      var deferred = $q.defer();
      var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
      var request = store.get(key);
      request.onsuccess = function (e) {
        console.log('idb.get onsuccess ', e.target.result);
        deferred.resolve(e.target.result.data);
        $rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
      };
      request.onerror = function (e) {
        console.log('idb.get onerror', e);
        deferred.reject(e);
      };
      return deferred.promise;
    };
  });

测试可以是:

'use strict';
describe('idb', function () {

  beforeEach(module('main'));

  var idb;
  var idbOpened;

  beforeEach(angular.mock.inject(function (_idb_) {
    idb = _idb_;
  }));

  beforeEach(function (done) {
    idbOpened = false;
    console.log(1);
    idb.open().then(function () {
      console.log(3);
      idbOpened = true;
      done();
    })
    console.log(2);
  });

  it('opens', function () {
    expect(idbOpened).toBe(true);
    console.log(4);
  });

  it('gets the put', function (done) {
    console.log(10);
    idb.put('666', 'bob').then(function () {
      console.log(12);
      idb.get('666').then(function (value) {
        console.log(13);
        expect(value).toBe('bob');
        done();
        console.log(14);
      })
    })
    console.log(11);
  });
});

然后测试输出:

LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 4
LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 10
LOG: 'idb.put(666, bob)'
LOG: 11
LOG: 'idb.put onsuccess'
LOG: 12
LOG: 'idb.get(666)'
LOG: 'idb.get onsuccess ', Object{id: '666', data: 'bob'}
LOG: 13
LOG: 14

丑陋的东西需要打电话

        $rootScope.$apply();

将承诺解决方案传播到'然后'在测试中的功能,因为 服务本身不需要它。

相关问题