1

在我的 JS 视图代码中,我使用jQuery UI 对话框组件来呈现弹出窗口。

我这样实例化它:

var popupDialog = $("#myPopupDiv").dialog({
    title: "My dialog",
    dialogClass: "myDialogClass",
    create: createHandler,
    draggable: false,
    width: width,
    height: height,
    autoOpen: false
});

请注意,它的 autoOpen 设置为“false”。我在“创建”处理程序中打开它:

var createHandler = function(event, ui) {
    //Vi venter litt for å sikre at popupen er "klar"
    setTimeout(function () {
        popupDialog.dialog("open");
    }, 5);
};

开放逻辑包含在 asetTimeout中以确保弹出窗口已准备就绪。

该代码在浏览器应用程序中运行良好,但是当我使用Jasmine 测试框架运行此代码时出现错误:

错误:无法在初始化之前调用对话框上的方法;试图调用方法“打开”

测试实际上通过了,所以清楚地呈现了该项目。但是我不喜欢运行测试时出现的错误!

我怀疑由于 Jasmine 测试运行得如此之快,组件还没有时间进行自我初始化。那么如何确保组件已初始化呢?我认为将这个逻辑放在“创建”处理程序中会处理这个问题,因为该事件是“在创建对话框时触发。 ”,但显然情况并非如此。

这是我测试它的方法:

it("should show my popup", function () {

    var myPopupLink = $('.popupLink');

    myPopupLink.click();

    //Wait until popup is shown
    waitsFor(function () {
        return !$('.myDialogClass').is(":hidden");
    }, "Popupen didn't show", 1000);

    //Check that the DOM is as expected
    expect($('.myDialogClass .popupContentDiv')).toExist();
    expect(...

    //Close popup
    myPopupLink.click();
    expect($('.myDialogClass .popupContentDiv')).not.toExist();

});

有人知道如何验证弹出对话框的初始化状态吗?还是有其他解决方法?

谢谢!

4

1 回答 1

2

您的测试的问题在于,它更像是验收测试而不是单元测试。您尝试测试的大部分内容都是 jQueryUi 的功能。您真正想要测试的是createHandler延迟打开对话框。所以你popupDialog.dialog应该是一个间谍,在那里你可以检查它是否在延迟后被调用。

目前你的代码真的很难测试,因为它直接基于 jquery。您应该考虑拥有可以注入依赖关系的函数,而不是依赖全局变量,例如popupDialog.

这是一个关于如何模拟所有依赖项的示例:

//mock out setTimeout so you dont have to wait in your test
jasmine.Clock.useMock();

//create a mock that will return from $().dialog()
var mockDialog = jasmine.createSpy('dialog');
// mock $ to return {dialog: mock that return {dialog: mockDialog}}
var mock$ = spyOn(window, '$').andReturn({
  dialog:jasmine.createSpy('$').andReturn({
    dialog: mockDialog
  })
})

expect(mock$).toHaveBeenCalled();

// call the create function    
window[mock$.mostRecentCall.args[0].create]();

jasmine.Clock.tick(4999);
expect(mockDialog$).not.toHaveBeenCalled();
jasmine.Clock.tick(5001);
expect(mockDialog$).toHaveBeenCalledWith('open');

如您所见,模拟所有 jQuery 依赖项非常复杂。因此,您可以重写代码以获得更好的可测试性,或者使用 selenium capybara 等将这些东西作为验收测试进行测试。

于 2013-01-20T11:54:40.340 回答