Функция узла, возвращающая 'undefined' до того, как запрос завершится с желаемым возвращаемым значением

Я знаю, что Node - это обратные вызовы. Я старался иметь это в виду при создании теста Jasmine, поскольку узнаю больше о Jasmine и Node.

Я написал очень простой тест с использованием jasmine-node, который должен ПОЛУЧАТЬ HTML-страницу, использовать 'cheerio' для загрузки и анализа возвращенного HTML и извлекать содержимое HTML-элемента. Мои тесты должны подтверждать точность текста, возвращаемого «cheerio».

Я обнаружил, что функция, которую я тестирую, возвращает undefined до завершения запроса. Вы можете увидеть это в результатах тестов. После того, как тесты сообщат об ошибке, вы увидите результаты console.log.

Я попытался использовать обратные вызовы для решения этой проблемы, и я видел сообщения об использовании таких библиотек, как async. Я пробовал использовать beforeEach () для хранения этих данных для теста.

Я не нашел правильный рецепт, и мне нужна помощь, пожалуйста.

index.html

<!doctype html>
<html>
<body>
<span class="title">Title Goes Here</span>
</body>
</html>

module1.js

var request = require('request');
var cheerio = require('cheerio');

exports.whoAmI = function () {
    'use strict';
    return "module1";
};

exports.testJq = function () {
    'use strict';
    var tipsotext = function (callback) {
        var output;
        request.get('http://localhost/test-test/index.html', function optionalCallback(err, httpResponse, body) {
            var $ = cheerio.load(body);
            output = $('.title').text();
            console.log("Executing callback with data: " + output);
            callback(null, output);
        });
    };

    tipsotext(function (err, data) {
        console.log("Returning with data: " + data);
        return data;
    });
};

module1-spec.js (мой тест)

var module1 = require("../src/module1.js");

describe("module1", function () {
    'use strict';

    it("should identify itself with whoAmI", function () {
        var test;
        test = module1.whoAmI();
        expect(test).toBe("module1");
    });
    it("should get data from the page", function () {
        var test;
        test = module1.testJq();
        expect(test).toBe("Title Goes Here");
    });
});

Результат моего неудавшегося теста

Failures:

  1) module1 should get data from the page
   Message:
     Expected undefined to be 'Title Goes Here'.
   Stacktrace:
     Error: Expected undefined to be 'Title Goes Here'.
    at null.<anonymous> (c:\test-test\spec\module1-spec.js:14:22)

Finished in 0.011 seconds
2 tests, 2 assertions, 1 failure, 0 skipped

Executing callback with data: Title Goes Here
Returning with data: Title Goes Here

person Ronan M    schedule 10.03.2016    source источник


Ответы (2)


  tipsotext(function (err, data) {
    console.log("Returning with data: " + data);
    return data;
});

Эта функция возвращает данные его анонимной функции => функции (err, data), поскольку этот метод является асинхронным, я думаю, вам следует заново продумать свой тест для поддержки асинхронных методов и добавить параметр обратного вызова в функцию testJq.

person cshion    schedule 10.03.2016

Реорганизован и, похоже, сейчас работает

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

Многие из моих изменений были сделаны на основе Тестирование асинхронных методов с помощью методов Jasmine run () и waitFor ()

Я здесь делаю много новичков? Есть плюсы с рекомендациями по исправлению?

module1.js

var request = require('request');
var cheerio = require('cheerio');
var title;
exports.whoAmI = function () {
    'use strict';
    return "module1";
};

exports.extractTitleFromBody = function (callback) {
    'use strict';
    request({
        url: 'http://localhost:63342/browserify-test/index.html', //URL to hit
        method: 'GET'
    }, function(error, response, body){
        if(error) {
            title = error;
        } else {
            var $ = cheerio.load(body);
            title = $('.title').text();
        }
        if (typeof callback === "function") {
            callback();
        }
    });
};
exports.getTitle = function () {
    'use strict';
    return title;
};

module1-spec.js

var module1 = require("../src/module1.js");

describe("module1", function () {
    'use strict';

    it("should identify itself with whoAmI", function () {
        var me;
        me = module1.whoAmI();
        expect(me).toBe("module1");
    });

    it("should make a real AJAX request and return the title", function () {
        var callback = jasmine.createSpy("spy");

        module1.extractTitleFromBody(callback);

        waitsFor(function() {
            return callback.callCount > 0;
        }, "The request timed out.", 5000);

        runs(function() {
            expect(callback).toHaveBeenCalled();
        });

        runs(function() {
            expect( module1.getTitle()).toBe("Title Goes Here");
        });
    });
});
person Ronan M    schedule 11.03.2016