4

Jasmineを使用して(特にTestacularを使用して)indexedDBセットアップをテストすることを検討しています。アプリの内部では、データベースを開いたり、作成したり、削除したりするために、問題なくデータベースを作成しています。データがサービスから正しく保存されていることを確認するために単体テストを作成しようとすると、タイムアウトなどのエラーが発生し続け、Chromeリソースパネル(現在Chrome 25でテスト中)に、正しいテーブル。indexedDBのテストを含む単純な実装とは何ですか?

4

3 に答える 3

7

indexedDBをテストする際に留意すべき点がいくつかあります。

  • indexedDBの非同期性を念頭に置き、Jasmine内で適切に処理する必要があります。非同期テストの鍵は、「ru​​ns」、「waits」、「waitsFor」など、jasmineに組み込まれているAsyncSpec関数の一部を使用することです。これらのメソッドを使用するときは、正しく配置するようにしてください。(つまり、beforeEach()の外にwaitsFor()を配置すると、タイムアウトエラーが発生する可能性があります。
  • 自分で作成したい場合を除いて、いくつかのラッパーの1つを使用してみてください。
  • 操作ごとに新しいトランザクションを作成するようにしてください。そうしないと、InvalidStateErrorsが発生します。
  • 組み込みのwaitsFor()を非同期テストで左右に使用したくない場合は、Jasmine.asyncのようなものを調べてください。

以下は、データベースに1つのアイテムを追加するための簡単なテストを示すために作成したものです。これは、ベンダープレフィックスのない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 );
        });
    });
于 2013-03-09T20:16:08.303 に答える
1

私はIDB ラッパーであるdb.jswaitsForに非常に大きなテスト スイートを持っています。それは主に を使用して非同期操作を行うことに依存しています。beforeEachこれをとと組み合わせるとafterEach、DB 接続のセットアップ/風袋引きを制御するために使用できるので便利です。いくつかの動作を確認したい場合は、 specsフォルダーをチェックしてください。

于 2013-03-10T23:43:09.543 に答える
0

これを見てください。これは、jasmine で indexeddb を使用する簡単な例がある github プロジェクトを参照しています。

于 2013-03-17T03:07:56.310 に答える