【问题标题】:Jasmine Testing Fancybox in Backbone - Spied Methods incorrectly passing throughJasmine 在 Backbone 中测试 Fancybox - 间谍方法错误地通过
【发布时间】:2013-08-13 14:05:11
【问题描述】:

我有一个模式登录视图,我正在使用 Jasmine 进行测试。我在测试登录按钮重定向时遇到了一个令人讨厌的问题。我已经将重定向放在一个方法中,以便我可以模拟它并测试调用,但是当我触发登录按钮上的点击事件时,间谍似乎被忽略了。

这是我正在测试的视图...

define(['ministry', 'models/m-auth', 'helpers/cookie-manager', 'text!templates/modals/login.html', 'jquery.custom'],
function (Ministry, Authentication, CookieManager, TemplateSource) {
    var loginView = Ministry.SimpleView.extend({

        name: 'Login',

        el: "#popupLoginWrapper",

        template: Handlebars.compile(TemplateSource),

        events: {
            'submit #loginForm': 'signIn'
        },

        redirectToOrigin: function () {
            // TODO: Change location to member home when implemented
            location.href = '/#/jqm';
        },

        signIn: function (e) {
            var that = this;

            e.preventDefault();

            // As we have no input yet log in manually using the auth model...
            var authData = new Authentication.Request({
                requestSource: $('#requestSource').text(),
                apiKey: $('#apiKey').text(),
                username: '*****',
                password: '*****'
            });

            // This saves the login details, generating a session if necessary, then creates a cookie that lasts for 1 hour
            authData.save(authData.attributes, {                    
                success: function () {
                    if (authData.generatedHash !== undefined && authData.generatedHash !== null && authData.generatedHash !== '')
                        CookieManager.CreateSession(authData.generatedHash);
                        that.redirectToOrigin();
                }
            });
        },
    });

    return loginView;
});

(它目前使用硬编码帐户登录 - 连接实际控件是下一项工作)。这是有问题的测试(为了简单起见,我将所有前后都合并到测试中)...

        var buildAndRenderView = function (viewObject) {
            viewObject.render();
            $('#jasmineSpecTestArea').append(viewObject.el);
            return viewObject;
        };

        it("signs in when the 'Sign In' button is clicked", function () {
            spyOn(objUt, 'redirectToOrigin').andCallFake(Helper.DoNothing);
            spyOn(Backbone.Model.prototype, 'save').andCallFake(function (attributes, params) {
                params.success();
            });

            $('body').append('<div id="jasmineSpecTestArea"></div>');
            $('#jasmineSpecTestArea').append('<section id="popupLoginWrapper"></section>');
            objUt = new View();
            buildAndRenderView(objUt);

            objUt.$('#loginForm button').click();

            expect(objUt.redirectToOrigin).toHaveBeenCalled();

            $('#jasmineSpecTestArea').remove();
        });

一些简短的理由:我将绝大多数视图作为独立组件进行处理,然后在称为区域的自定义视图变体中呈现(以 Marionette 为模型) - 我通常认为这是一个很好的整洁实践,可以帮助我保持跟踪应用程序中的内容与给定“空间”中的内容分开。此策略似乎不适用于诸如此类的花哨模式,因此渲染发生在隐藏的现有 DOM 元素中,然后移动到该区域中,因此需要将代码附加 'popupLoginWrapper' 到测试区域.

如果我直接使用空事件参数调用登录方法,上述相同的测试也会失败。 Jasmine 给了我以下错误“错误:预期是间谍,但得到了功能。” (这是有道理的,因为它调用的是 redirectToOrigin 的实际实现而不是间谍。

我有类似的测试通过了,问题似乎是触发 params.success(),但这是测试所必需的。

附加:禁用测试后,我发现此问题会影响此模式的大多数测试。通过单步执行,我可以看到在某些情况下应用了 spy 并执行了 spy 代码,但之后似乎触发了真正的成功调用。

【问题讨论】:

    标签: javascript backbone.js jasmine fancybox-2


    【解决方案1】:

    我似乎已经解决了这个问题 - 我不确定如何解决;几天后我才刚刚接触到它 - 测试现在看起来像这样......

                var buildAndRenderView = function (viewObject) {
                    viewObject.render();
                    $('#jasmineSpecTestArea').append(viewObject.el);
                    viewObject.postRender();
                    return viewObject;
                };
    
                   it("signs in when the 'Sign In' button is clicked", function () {
                        $('body').append('<div id="jasmineSpecTestArea"></div>');
                        $('#jasmineSpecTestArea').append('<section id="popupLoginWrapper"></section>');
                        objUt = new View();
                        spyOn(objUt, 'redirectToOrigin').andCallFake(Helper.DoNothing);
                        spyOn(objUt, 'displayError').andCallFake(Helper.DoNothing);
                        spyOn(Backbone.Model.prototype, 'save').andCallFake(function (attributes, params) {
                            params.success();
                        });
    
                        objUt = buildAndRenderView(objUt);
                        objUt.$('#loginForm button').click();
    
                        expect(objUt.redirectToOrigin).toHaveBeenCalled();
                        expect(objUt.displayError).not.toHaveBeenCalled();
                        $('#jasmineSpecTestArea').remove();
                    });
    

    添加了 displayError 调用,因为我从最初的问题开始就包装了错误警报机制,所以并不是特别相关。我在修复测试后将一些变量集拆分为 postRender,所以这也不相关。

    问题似乎在于调用 buildAndRenderView 方法而没有将返回值设置为对象。通过改变这个...

    buildAndRenderView(objUt);
    

    到...

    objUt = buildAndRenderView(objUt);
    

    问题自行解决。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多