0

PhoneGapとKnockout.jsを使用してモバイルアプリを構築しており、ユニットテストにQUnitを使用しています。私は小さな問題に遭遇しました。

これは本質的にフォトギャラリーであり、テストの1つの一環として、最初にAJAXを介してロードされるすべてのアルバムを取得したいと思います。次に、最初のアルバムのすべての写真を返したいと思います。

アルバムだけを入手して、その機能の単体テストを行うことはできますが、写真を取得するためにアルバムを拡張するのは非常に困難です。

私のビューモデルはAlbumViewModelと呼ばれ、albums()とphotos()という2つの監視可能な配列があります。アプリケーションが最初に開かれると、アルバムはAJAXを介して自動的にフェッチされ、albums()に結果が入力されます。アルバムが選択されると、getPhotos()に渡されます。getPhotos()はalbums()を無効にし、アルバム内の写真をフェッチして、photos()に保存します。

アルバムの単体テストは次のとおりです。

test("Check albums created", function () {
    'use strict';

    // Stop the test
    stop();

    // Declare variables used
    var avmodel;

    // Create AlbumViewModel
    avmodel = new AlbumViewModel();

    // Wait for album fetch
    avmodel.albums.subscribe(function () {
        // Check albums length is more than 0
        ok(avmodel.albums().length > 0, "Albums length is " + avmodel.albums().length);

        // Run the tests for the albums
        start();
    }); 
}); 

これはAJAXを介してサーバーからデータをフェッチするため、albums()の監視可能な配列が設定されるまで実行を遅らせる必要がありました。

これは完全に正常に機能します。ただし、写真を取得するためのテストはより問題があります。基本的に、最初にアルバムをフェッチする必要があります。次に、アルバムがフェッチされたら、そのうちの1つを取得して写真をフェッチします。さて、上記のように、albums.subscribeイベントにサブスクライブし、完了したらテストを実行するだけで、アルバムを使用してこれを達成しました。だから、それはphotos()をテストするための方法のように見えました。

写真をテストするために私が書いたものは次のとおりです。

test("Check photos created", function () {
    'use strict';

    // Stop the test
    stop();

    // Declare variables used
    avmodel;

    // Create AlbumViewModel
    avmodel = new AlbumViewModel();

    // Wait for album fetch
    avmodel.albums.subscribe(function () {

        // Only check the first time it runs
        var albumToGet;
        if(typeof albumToGet === "undefined") {
            // Get the album to examine
            if (avmodel.albums()) {
                albumToGet = avmodel.albums()[0];

                // Subscribe to the photos observableArray
                avmodel.photos.subscribe(function () {
                    var photos = avmodel.photos(albumToGet);

                    // Check photos length more than 0
                    ok(photos.length > 0, "Photos length is " + photos);

                    // Restart
                    start();
                }); 

                // Get the photos for this album
                avmodel.getPhotos(albumToGet);
            }   
        }   
    }); 
}); 

基本的に、最初にAJAX応答が受信されて処理されるまでアルバムの詳細の取得を遅らせる必要があります。次に、それが完了したら、albumToGetオブジェクトを最初のアルバムに設定してgetPhotosに渡します。次に、写真をフェッチするためのAJAX応答が受信されて処理されるまで、テストの実行を遅らせます。

albums()のサブスクリプション内のphotos()observable配列をサブスクライブできると思いましたが、残念ながらChromeの開発者ツールは次のエラーを返します。

Uncaught RangeError: Maximum call stack size exceeded

これは無限ループを示唆しているように思われます。つまり、サブスクリプションのネストは最善のアプローチではない可能性があります。誰かが私が迷ったところを指摘できますか?QUnitとKnockout.jsの両方を使用するのはこれが初めてなので、少し深みがあります。

TL; DR:QUnitを使用してKnockout.jsアプリケーションの単体テストを行っています。コードをテストするために、1つのメソッドがAJAXを介して機能するのを待ってから、返されたデータを取得し、それをAJAXを介して機能する2番目のメソッドに渡す必要があります。最初のメソッドへのサブスクライブは、それをテストするためだけに機能しましたが、最初のメソッド内に2番目のサブスクリプションをネストすることはできません。私がこれをどのように行うことができるかについての提案はありますか?

4

1 に答える 1

1

取得している無限ループは、ネストされたサブスクリプションが原因ではありません。

エラーは、内部サブスクリプションの開始時にこの行が原因で発生します

var photos = avmodel.photos(albumToGet);

代わりにあなたは持っているべきです

var photos = avmodel.photos();

基本的に、カスタムアルバムオブジェクトを監視可能な配列に渡しているため、例外が発生しています。

于 2013-03-01T03:20:36.583 に答える