【问题标题】:How to test json inside function using jasmine?如何使用茉莉花测试函数内部的json?
【发布时间】:2016-08-24 21:26:28
【问题描述】:

这是我要测试的代码:

function loadNotification(searchOption, searchKey) {
   var url = '@URLs.API.Notifications.Past' + '?searchOption=' + searchOption + '&searchValue=' + searchKey;
   $.getJSON(url)
      .done(function (nData) {
        //some code here
      })
      .fail(function (jqXHR, status, error) {
        showError('There was an error while fetching the records. Please try after some time. (' + jqXHR.status + ':' + jqXHR.statusText + ')');
      });
}

使用 jasmine,我如何测试 json 文件是否失败?我正在考虑使用 .done.fail 但我不确定是否可行。我对 json 了解不多。谁能帮帮我?

【问题讨论】:

    标签: json jasmine


    【解决方案1】:

    在测试 AJAX 请求(以及类似的,获取 json 文件等)时,检查您的代码是否可以处理完成和失败总是一个好主意。您还应该模拟您测试的数据,不要过多依赖应用程序中的实际端点或它尝试下载的文件。您希望测试尽可能快地运行。

    使用 Jasmine 你可以做一些事情:

    使用间谍:

    spyOn 是一个函数,它可以存根给定函数并跟踪传递给它的参数类型,可以查看调用它的其他函数,甚至在它被监视的代码执行时返回特定值。

    您可以使用 spy 来查看 $.get 请求是否会发生,然后您可以说返回一个特定的值,然后继续测试程序。

    使用 Jasmine Ajax 插件

    这是我喜欢在我的测试中使用的。 Jasmine 有一个非常好的插件ajax.js。它简化了任何 ajax 功能的测试。我喜欢做的是模拟实际请求,因此当您的代码尝试获取文件/响应时,代码将忽略实际调用并模拟它,返回您可以指定的假数据。

    在我开始之前,我还喜欢将我的 ajax 方法放在一个单独的函数中,它只会返回一个 Promise。它更容易阅读/测试/维护,所以例如你可以重写它:

    this.loadNotificationCall = function(searchOption, searchKey) {
        var url = '@URLs.API.Notifications.Past' + '?searchOption=' + searchOption + '&searchValue=' + searchKey;
        return $.getJSON(url)
    } 
    
    this.loadNotification() {
        return this.loadNotificationCall()
            .done(function (nData) {
                //some code here
            })
            .fail(function (jqXHR, status, error) {
                showError('There was an error while fetching the records. Please try after some time. (' + jqXHR.status + ':' + jqXHR.statusText + ')');
            });
    }
    

    如果您使用虚拟数据加载测试应用程序,我猜您希望 ajax 请求文件具有特定路径。

    您正在查看您可以输出的最基本的默认版本

    '@URLs.API.Notifications.Past' + '?searchOption=' + searchOption + '&searchValue=' + searchKey;
    

    假设是这样的

    //'someapi?searchOption=1&searchValue=abc'
    

    该 url 需要与您的应用程序将尝试联系的内容完全匹配。检查你的调试器/提琴手,看看是什么以防万一。如果不匹配(包括它尝试发送的数据),模拟将失败,并且测试将超时。错误通常看起来像Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

    一旦你做对了,你就可以在下面的例子中模拟那个 url:

    describe('when user gets the data', function() {
    
    var sut = null;
    var testCall = null;
    var dummyData = {
        name: 'Jon Snow'
    };
    beforeEach(function() {
        jasmine.Ajax.install();
        jasmine.Ajax.stubRequest("someapi?searchOption=1&searchValue=abc").andReturn({
                responseText: JSON.stringify(dummyData)
        });
    
        sut = new yourApplication();
        testCall = sut.loadNotification();
    });
    
    afterEach(function() {
        jasmine.Ajax.uninstall();
    });
    
    // actual tests here
    
    });
    

    我也很确定您可以在这些模拟网址中使用通配符,所以这也应该是有效的:jasmine.Ajax.stubRequest("someapi?(.*)").andReturn(//

    所以现在发生的情况是,如果您测试将使用 $.get 调用您的方法的东西,则该请求不会发生在您的服务器上,而是会被模拟并返回我们的虚拟数据。在这个例子中,它是一个带有name: 'Jon Snow'的简单对象

    现在,您想要一个看起来像这样的测试:

    it('should populate name', function(done) {
        testCall
            .done(function() {
                expect(sut.name).toEqual('Jon Snow');
                done();
            });
    });
    

    您将 done 参数传递给测试,以便在调用完成之前它不会完成。如果您在浏览器中调试它,您将看到文件中的代码将进入 done 方法并继续工作,因为它是一个真实的请求。 done(nData) 中的数据将成为我们的虚拟对象name: Jon Snow

    如果你想测试一个失败的代码,你可以给 ajax 插件添加一些额外的设置:

    jasmine.Ajax.stubRequest("someapi?searchOption=1&searchValue=abc").andReturn({
        status: 500,
        responseText: "{}"
    });
    

    我希望我没有让你感到厌烦,我知道有更简单的方法(比如只是在 'ajax' 上执行 $.spy 并查看最近的调用等,但我喜欢我的方法,已经奏效了非常好,我可以测试多个调用、链接调用以及更多很酷的场景。

    【讨论】:

    • 感谢@kasperoo 的详细回复。我会继续用我的测试来尝试这些。我很感激!希望我可以让它工作。
    • 如果我无法更改具有 ajax 调用的函数(它是由另一个开发人员编写的),我可以继续使用您上面提供的代码来模拟它吗?
    • 正确,假设返回了承诺
    • 我对此有点困惑:sut = new yourApplication();我不知道该穿什么。即时测试功能位于 cshtml 文件中。我在这里错过了什么吗?如果这看起来是一个愚蠢的问题,我很抱歉,但我对这一切真的很陌生。
    • SUT 表示System Under Test。它是您测试的类的一个实例。它是启动您的应用程序的任何东西,您的主要对象。没有愚蠢的问题!看起来你的第一个问题是 JS 是 HTML 页面的一部分 - 你真的需要将它分开,否则很难在那个设置中测试任何东西。您应该将所有函数(方法)绑定在一个可以实例化的对象中(使用new)并使用。至少应该这样做。
    猜你喜欢
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多