0

我正在使用 PhoneGap 和 Knockout.js 构建一个移动应用程序,并且我正在使用 QUnit 对其进行单元测试。我遇到了一个小问题。

它本质上是一个照片库,作为其中一项测试的一部分,我想首先获取所有通过 AJAX 加载的相册。然后我想返回第一张相册中的所有照片。

我可以单独获取相册,并对该功能进行工作单元测试,但我在扩展它以获取照片时遇到了很多困难。

我的视图模型称为 AlbumViewModel,它有两个可观察的数组,称为专辑()和照片()。首次打开应用程序时,会通过 AJAX 自动获取相册,并用结果填充相册()。当一个相册被选中时,它被传递给 getPhotos(),它使相册() 无效并获取相册中的照片,将它们存储在 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() 可观察数组。

这绝对没问题。但是,获取照片的测试存在更多问题。我基本上需要首先获取相册,然后,一旦它们被获取,获取其中一张并获取照片。现在,正如您在上面看到的,我通过订阅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 响应。

我以为我可以订阅相册()一个订阅中的照片()可观察数组,但不幸的是,Chrome的开发人员工具返回以下错误:

Uncaught RangeError: Maximum call stack size exceeded

这似乎暗示了一个无限循环,可能意味着嵌套订阅可能不是最好的方法。谁能指出我误入歧途的地方?因为这是我第一次同时使用 QUnit 和 Knockout.js,所以我感觉有点超出我的深度。

TL;DR:我正在使用 QUnit 对 Knockout.js 应用程序进行单元测试。需要等待一种方法通过 AJAX 工作,然后获取返回的数据并将其传递给同样通过 AJAX 工作的第二种方法,以便测试代码。订阅第一种方法仅用于测试,但不能在第一个订阅中嵌套第二个订阅。关于我如何做到这一点的任何建议?

4

1 回答 1

1

您得到的无限循环不是因为嵌套订阅。

该错误是由内部订阅开头的这一行引起的

var photos = avmodel.photos(albumToGet);

相反,你应该有

var photos = avmodel.photos();

您实际上是将自定义专辑对象传递到可观察数组中,这就是导致异常的原因。

于 2013-03-01T03:20:36.583 回答