jasmine - 使用 Jasmine 进行浏览器的 IndexedDB 测试

标签 jasmine indexeddb karma-runner

我正在考虑使用 Jasmine 测试 indexedDB 设置(特别是 Testaulous)。在应用程序内部,我正在编写要打开、创建、删除等的数据库,没有任何问题。现在,当我尝试编写单元测试以确保正确从服务保存数据时,我不断收到错误,例如超时,并且 Chrome 资源面板(当前在 Chrome 25 上测试)不显示使用正确的表格。涉及测试indexedDB 的简单实现是什么?

最佳答案

测试时需要记住一些事情indexedDB .

  • 您必须牢记indexedDB的异步性质,并在Jasmine内部正确处理它。异步测试的关键是使用 jasmine 内置的一些 Async Spec函数如“runs”、“waits”和“waitsFor”。使用这些方法时请确保正确放置它们。 (即在 beforeEach() 之外放置 waitsFor() 可能会导致超时错误。
  • 除非您想自己编写,否则请尝试使用 one several 包装最适合您的内容。
  • 确保为每次操作创建新交易,否则您将收到 InvalidStateErrors。
  • 如果您希望避免在异步测试中使用内置的 waitsFor() left 和 right,您可能希望查看类似 Jasmine.async 的内容。

以下是我为了演示向数据库添加一项的简单测试而所做的事情。这应该适用于 Chrome 24+、FF 16+ 和 IE10(假设您有带有 Deferred 的 jquery 版本),没有供应商前缀。不过,我强烈建议使用上述 IDB 包装器/插件之一。这里可能需要添加更多错误输出,但希望这有助于入门。

describe("Database interaction", function () {

        var settings = {
            name: "TEST",
            version: 1
        };
        var stores = [
            {name: "store1", keyPath: "id"},
            {name: "store2", keyPath: "id"},
            {name: "store3", keyPath: "id"}
        ];
        var db;

        function setupDB(){
            var dbRequest = window.indexedDB.open( settings.name, settings.version),
                dbDfd = $.Deferred();

            dbRequest.onsuccess = function( event ) {
                console.log("Opened DB");
                db = dbRequest.result;
                dbDfd.resolve( db );
            };
            dbRequest.onblocked = function( event ){
                console.error("DB connection blocked");
                db.close();
                setupDB();
            };
            dbRequest.onerror = function( event ){
                console.error("DB connection issues");
                dbDfd.reject();
            };
            dbRequest.onupgradeneeded = function(){
                var i, cur;
                db = dbRequest.result;

                //Create non-existant tables
                for(i=0; i < stores.length; i+=1){
                    cur = stores[i];
                    db.createObjectStore( cur.name,  {keyPath: cur.keyPath, autoIncrement: true});
                }
            };
            return dbDfd.promise();
        }

        beforeEach(function(){
            var done = false;
            runs( function(){
                var delRequest = indexedDB.deleteDatabase("TEST");
                delRequest.onsuccess = function( event ){
                    console.log("DB Deleted");

                    setupDB()
                        .then(function(db){
                            console.log("DB Setup with stores: ", db.objectStoreNames );
                            done = true;
                        })
                };
                delRequest.onerror = function(event){
                    console.log("DB Err: ", event );
                    done = true;
                };
            });
            waitsFor( function(){ return done; }, "Database never created..", 10000 );
        });

        it('should add an item to store1', function(){
            var done = false;
            //Open a transaction with a scope of data stores and a read-write mode.
            var trans = db.transaction( stores.map(function(s){return s.name;}), 'readwrite');

            //"objectStore()" is an IDBTransaction method that returns an object store
            //that has already been added to the scope of the transaction.
            var store = trans.objectStore('store1');

            var req = store.add({"id": 2, "foo":"bar"});
            req.onsuccess = function(){

                //Remember to not access store or trans (from above), or this.source.prototype functions as we can only access those in a new transaction
                //Added an object to the store, expect result to be ID of item added
                expect( this.result ).toBe( 2 );
                //Some other expectations
                expect( this.source.name ).toBe("store1");
                expect( this.source.keyPath ).toBe("id");
                expect( this.source.autoIncrement ).toBe( true );
                expect( this.source.indexNames.length ).toBe( 0 );
                expect( this.transaction.mode ).toBe("readwrite");
                expect( this.transaction.db.name ).toBe("TEST");
                done = true;
            };
            req.onerror = function(){
                console.log("Error adding object to store");
                done = true;
            };
            waitsFor(function(){ return done; }, "Didn't add store item", 10000 );
        });
    });

关于jasmine - 使用 Jasmine 进行浏览器的 IndexedDB 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15315437/

相关文章:

ruby-on-rails - 在 rails 中使用带有 Jasmine 的 Spork

javascript - AngularJS + Jasmine : Comparing objects

javascript - indexedDB规范是否支持保存具有空值的项目?

javascript - indexeddb:如何获取请求结果和游标值

angular - 如何摆脱警告将原始 CLI 选项传递给 `new Server(config, done)` 已弃用

angularjs - 测试某些元素是否可见

javascript - 如何使用内部调用返回 promise 的函数的 jasmine-node 测试函数?

android - 如何在不丢失应用程序数据的情况下删除人行横道?

google-chrome - 引用错误 : expect is not defined

angular - e2e如何在 Angular Protractor 中测试登录成功案例