Проблема с модульным тестированием модели представления в Knockout.js

Я создаю мобильное приложение, используя PhoneGap и Knockout.js, и использую QUnit для его модульного тестирования. Я столкнулся с небольшой проблемой.

По сути, это фотогалерея, и в рамках одного из тестов я хочу сначала получить все альбомы, которые загружаются через AJAX. Затем я хочу вернуть все фотографии из первого альбома.

Я могу получить альбомы в одиночку и пройти тестирование на работоспособность этой функции, но у меня много трудностей с расширением для получения фотографий.

Моя viewmodel называется AlbumViewModel, и у нее есть два наблюдаемых массива, называемые album () и photos(). Когда приложение открывается в первый раз, альбомы выбираются автоматически через AJAX, а альбомы () заполняются результатами. Когда альбом выбран, он передается в getPhotos(), которая аннулирует album () и извлекает фотографии из альбома, сохраняя их в 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, мне нужно было отложить выполнение до тех пор, пока не будет заполнен наблюдаемый массив album ().

Это работает абсолютно нормально. Тем не менее, тест для получения фотографий является более проблематичным. Мне нужно в первую очередь получить альбомы, а затем, как только они будут получены, получить один из них и получить фотографии. Теперь, как вы можете видеть выше, я выполнил это с помощью альбомов, просто подписавшись на событие album.subscribe и выполнив тест после его завершения. Итак, это похоже на способ тестирования фотографий ().

Вот что я написал для тестирования фотографий:

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 для получения фотографий не будет получен и обработан.

Я думал, что мог бы подписаться на массив наблюдаемых photos () внутри подписки на album (), но, к сожалению, инструменты разработчика Chrome возвращают следующую ошибку:

Uncaught RangeError: Maximum call stack size exceeded

Казалось бы, это предполагает бесконечный цикл, возможно, означающий, что вложенные подписки могут быть не лучшим подходом. Кто-нибудь может указать, где я сбился с пути? Я чувствую себя немного не в своей тарелке, так как я впервые использую и QUnit, и Knockout.js.

TL; DR: я тестирую приложение Knockout.js с помощью QUnit. Нужно подождать, пока один метод заработает через AJAX, затем получить возвращенные данные и передать его второму методу, который также работает через AJAX, чтобы протестировать код. Подписка на первый метод работала только для того, чтобы проверить это, но не может вложить вторую подписку внутри первой. Какие-нибудь предложения относительно того, как я мог сделать это?

1 ответ

Решение

Вы получаете бесконечный цикл не из-за вложенной подписки.

Ошибка вызвана этой строкой в ​​начале внутренней подписки

var photos = avmodel.photos(albumToGet);

Вместо этого вы должны иметь

var photos = avmodel.photos();

По сути, вы передаете свой пользовательский объект альбома в наблюдаемый массив, и именно это вызывает исключение.

Другие вопросы по тегам