Тестирование IndexedDB с Jasmine для браузеров

Я изучаю возможность тестирования установки indexedDB с использованием Jasmine (в частности, с Testacular). Внутри приложения я пишу базу данных для открытия, создания, удаления и т. д. без каких-либо проблем. Теперь, когда я пытаюсь написать модульный тест, чтобы убедиться, что данные сохраняются из службы правильно, я продолжаю получать ошибки, такие как тайм-ауты, а панель ресурсов Chrome (в настоящее время тестируется в Chrome 25) не показывает базу данных, созданную с помощью правильные таблицы. Что такое простая реализация, включающая тестирование indexedDB?


person Ryan Q    schedule 09.03.2013    source источник
comment
я написал макет IndexedDB для тестирования угловой службы, которая обертывает IndexedDB. я использовал жасмин/карма для тестирования. github.com/szimmers/mock-indexeddb   -  person zim    schedule 25.03.2014


Ответы (3)


Есть несколько моментов, о которых следует помнить при тестировании indexedDB.

  • Вы должны помнить об асинхронной природе indexedDB и соответствующим образом обрабатывать ее внутри Jasmine. Ключом к асинхронным тестам является использование некоторых встроенных в jasmine функций Async Spec, таких как "runs", " ждет" и "ждет". Убедитесь, что при использовании этих методов вы правильно размещаете их. (IE Размещение waitsFor() за пределами beforeEach() может привести к ошибкам тайм-аута.
  • Если вы не хотите писать свои собственные, попробуйте использовать один из несколько оберток с тем, что лучше всего подходит для вас.
  • Убедитесь, что вы создаете новые транзакции для каждой манипуляции, иначе вы получите InvalidStateErrors.
  • Если вы хотите избежать использования встроенного waitsFor() влево и вправо с асинхронными тестами, вы можете изучить что-то вроде Jasmine.async< /а>

Следующее — это то, что я сделал, чтобы продемонстрировать простой тест для добавления одного элемента в базу данных. Это должно работать в Chrome 24+, FF 16+ и IE10 (если у вас есть версия jquery с Deferred) без префиксов поставщиков. Однако я настоятельно рекомендую использовать одну из вышеупомянутых оболочек/плагинов 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 );
        });
    });
person Ryan Q    schedule 09.03.2013

У меня есть довольно большой набор тестов в db.js, который является оболочкой IDB и в основном полагается на использование waitsFor для выполнения асинхронных операций. Сочетание этого с beforeEach и afterEach полезно, поскольку их можно использовать для управления вашей настройкой/отключением соединения с БД, проверьте specs, если вы хотите увидеть некоторые из них в действии.

person Aaron Powell    schedule 10.03.2013
comment
На самом деле я реализовал часть afterEach перед этим постом, но вместо того, чтобы использовать ту же базу данных, я экспериментировал с созданием новой в beforeEach и удалением ее в afterEach, чтобы ускорить тесты и не беспокоиться о блокировке транзакций. - person Ryan Q; 12.03.2013

Взгляните на это. Это относится к проекту github, в котором есть простой пример использования indexeddb в jasmine.

person rgaskill    schedule 17.03.2013