0

我目前正在开发一个我决定使用 JQuery Mobile 实现的移动应用程序。但是,由于它将是一个官方应用程序,因此需要我对其进行测试,因此我决定使用我在学校学会处理的 Jasmine。

目前我有一个客户端和服务器端,它们使用 AJAX ( $.getJSON) 请求进行通信。

当这些 AJAX 请求之一被转发到它的callback方法时,它将调用一个Notification类来实现div其中的通知。

我目前的问题是,当我使用以下代码时,它似乎总是有效:

window.setTimeout(function () {
    var expectedResult = "error";
    var result = $("#test .ui-content .contentContainer .notification").text();
    expect(result).toEqual(expectedResult);
}, 4000);

然而,几天后,我开始使用一个新模块,并编辑了这些值,它一直在工作,这将是非常错误的,因为它的旧代码 - 不存在 - 代码。

所以我注意到这个单元测试从未真正起作用。

所以我开始寻找替代方法并找到了runsandwaitsFor函数,但我似乎无法让它们工作。

所以这里是一个测试:

it('should display an error when trying to add a new contact', function () {
    runs(function () {
        var contact = new Contact();
        contact.addContact();
    });

    waitsFor(function () {
        expect($("#test .ui-content .contentContainer .notification")).toBeVisible();
    }, 5000);

    var expectedResult = "asdf";
    var result = $("#test .ui-content .contentContainer .notification").text();
    expect(result).toEqual(expectedResult);
});

回调方法:

this.addContact_callback = function (data) {
    $('#createContactForm')[0].reset();
    $('.ui-dialog').dialog('close');
    window.setTimeout(function () {
        (new Contact()).retrieveContactList();
        (new NotificationBox()).show(data.message[0], data.message[1]);
    }, 250)
};

我的通知:

function NotificationBox() {
    this.show = function (message, type) {
        var activePage = $("body .ui-page-active").attr("id");
        var create = "<div class='notification " + type + "'>" + message + "</div>";
        $("#" + activePage + " .ui-content .contentContainer .notification").remove();
        $("#" + activePage + " .ui-content .contentContainer").prepend(
            $(create).hide().fadeIn('slow').delay(2500).fadeOut('slow', function () {
                $(this).remove();
            })
        );
    };
}

我希望有人能够为我提供解决这个主要问题的方法。

此致, Larssy1

4

2 回答 2

1

您正在滥用该waitsFor方法。如果你阅读官方文档waitsFor需要返回一个值来指示等待时间是否结束。

您可能想要做的是以下内容:

waitsFor(function () {
    return $("#test .ui-content .contentContainer .notification").is(":visible");
}, 5000);

您还缺少测试最后一部分的运行块。

runs(function () {
    var expectedResult = "asdf";
    var result = $("#test .ui-content .contentContainer .notification").text();
    expect(result).toEqual(expectedResult);
});
于 2013-10-16T14:50:25.413 回答
0

尽管它可能不被视为一种解决方案,但它确实创建了更好的可管理和可测试的代码。

在我给定的代码示例中,我将代码转发到外部回调方法,就像我使用的给定代码一样addContact_callback。跟踪实际结果的唯一方法是确定notification元素类的文本是什么。

话虽如此,很明显,如果您遇到此问题,则可能编写了脏代码。

出于这个原因,我将代码更改为更好的代码,它使用内部回调方法。这意味着代码看起来像这样:

function handleSomething () {
    this.retrieveSomething(function (data) {
        console.log(data);
    });
}

function retrieveSomething (callback) {
    $.ajax({
        type: "GET",
        url: "127.0.0.1/my.php",
        success: function (data, status, xhr) {
            return callback($.parseJSON(data);
        }
    });
}

这确保我的代码更容易测试,因为我可以为单元测试实现自定义回调函数。

还记得旧的单元测试吗?好吧,这来自:

window.setTimeout(function () {
    var expectedResult = "error";
    var result = $("#test .ui-content .contentContainer .notification").text();
    expect(result).toEqual(expectedResult);
}, 4000);

至 :

var contact = new Contact();
contact.retrieveSomething(function (data) {
    var expectedResult = (new Contact()).errorMessages[4];
    expect(data.message).toBe(expectedResult);
});

结论:确保您始终可以测试您的返回输出,而不是简单地将其移动到 UI,然后尝试测试结果是否与您预期的相同。

于 2013-10-17T08:57:53.537 回答