【问题标题】:How test Service working with IndexedDB in AngularJS如何在 AngularJS 中使用 IndexedDB 测试服务
【发布时间】:2015-12-01 08:14:32
【问题描述】:

我在 AngularJS 中有应用程序,我在其中提供服务,将数据存储到 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
    };
}]);

我想使用单元测试(茉莉花)来测试这段代码。所以我写了这个:

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 服务中打开函数返回所有记录?

我不知道为什么,但是在这个测试中没有创建数据库

console.log(IndexedDb.findAll());
print: Promise{$$state: Object{status: 2, value: 'IndexDB is not open yet!'}} 所以没有创建 Db。 接下来如何在返回的承诺中使用 expect(..).toEqual() 或其他东西?

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine indexeddb


    【解决方案1】:

    让我们来服务吧:

    /*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();
    

    将承诺解决方案传播到测试中的“then”函数,因为 服务本身不需要它。

    【讨论】:

    • 谢谢,看起来不错。但是如果我使用我的服务,所以我调用 idb.add... 而不是 idb.put 和 idb.getById 在日志之后:11 是错误:错误:超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调.我在这里找到:stackoverflow.com/questions/22604644/… 连接到 done() 但我不知道如何修复它。我在 idb.getById(....) 的回调中调用 done() 谢谢
    猜你喜欢
    • 2012-10-12
    • 2014-09-04
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2014-06-17
    相关资源
    最近更新 更多