【问题标题】:Mocking $httpBackend - how to handle "Unexpected request, No more request expected"?模拟 $httpBackend - 如何处理“意外的请求,没有更多的请求”?
【发布时间】:2014-03-14 12:32:28
【问题描述】:

我有一个 Jasmine 测试,编码如下:

  it ("should send correct message to server to get data, and correctly set up scope when receiving it", function(){
    $httpBackend.when('GET', 'https://localhost:44300/api/projectconfiguration/12').respond(fakedDtoBase);
    $routeParams.projectId=fakeId; // user asks for editing project
    scope.$apply(function(){
        var controller=controllerToTest(); // so controller gets data when it is created
    });
    expect(scope.projectData).toEqual(fakedDtoBase);
});

它有点工作,但我得到了错误:

Error: Unexpected request: GET views/core/main/main.html
No more request expected
    at $httpBackend (C:/SVN/src/ClientApp/client/bower_components/angular-mocks/angular-mocks.js:1207:9)
    at sendReq (C:/SVN/src/ClientApp/client/bower_components/angular/angular.js:7800:9)
    at $http.serverRequest (C:/SVN/src/ClientApp/client/bower_components/angular/angular.js:7534:16)
    (more stack trace)....

我确实意识到我可以模拟其他所有呼叫。但是假设我不在乎我的测试还想加载什么,因为它可能会调用其他一些东西。 我如何确保所有其他请求都“默默地发生”,也许为其他所有请求提供一个虚拟响应?

【问题讨论】:

    标签: angularjs jasmine karma-runner


    【解决方案1】:

    您的测试失败,因为发出了您未指定的请求。

    尝试添加:

    $httpBackend.when('GET', 'views/core/main/main.html').respond(fakedMainResponse);
    

    当然你也应该定义fakedMainResponse

    请查看documentation(请求期望与后端定义部分),其中说:

    请求期望提供了一种对请求进行断言的方法 由应用程序生成并定义这些请求的响应。 如果没有发出预期的请求,或者没有发出请求,则测试将失败 顺序错误。

    $httpBackend.when 的第二个参数实际上是一个RegExp。因此,如果您提供与所有其他请求匹配的RegExp,它应该可以工作。

    【讨论】:

      【解决方案2】:

      对于那些在 EndToEnd 测试中使用 httpBackend 来模拟 http 调用或只是模拟应用程序的整个 http 调用的用户,解决方案是在应用程序配置部分添加以下代码(根据模板的位置更改正则表达式):

      $httpBackend.whenGET(/^\/templates\//).passThrough();
      

      参考:https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend

      使用 angularjs 1.4 测试,在集成 ui-router 时解决类似问题

      【讨论】:

      • 不要在单元测试中这样做。还有其他加载模板的方法,例如 karma-html2js-preprocessor
      • 您好@Thomas,我想阅读您的“不要在单元测试中这样做”肯定背后的真正论据。我的回答的要点是,我们正在进行 endToEnd 测试并模拟 http 响应(重要的 API 服务),我们不关心模板的到来,通常对于测试调试来说,最好让它们尽可能干净。我同意使用 html2js 进行生产是必须的。
      • 使用 passThrough,您需要一个正在运行的服务器,您可以从中加载模板。您不希望在单元测试中出现这种依赖关系。
      • @Thomas 是对的。我从来没有通过 passThrough 工作,而且 karma-html2js-preprocessor 很容易,不用费心与所有其他 bs 斗争。
      【解决方案3】:

      我认为同样重要的是要注意,如果您有$digest(),您的期望应该遵循$digest,如下所示:

      _$rootScope_.$digest();
      $httpBackend.when('GET', 'views/core/main/main.html').respond(fakedMainResponse);
      // ...
      $httpBackend.flush(); // And remember to flush at the end
      

      【讨论】:

        【解决方案4】:

        您只需将 setTimeout 和 done 属性添加到您的刷新中即可防止它发生

        it('should get data in callback funcion', function (done) {
            $httpBackend.whenGET(/\/my-endpoint/).respond(mockDataResponse);
        
            apiFactory.getCurrencyFormat('en', function (res, err) {
                expect(res.a).to.deep.equal(generalMock.a);
                expect(res.b).to.deep.equal(generalMock.b);
            });
        
            setTimeout(function () {
                done();
                $httpBackend.flush();
            }, 200);
        });
        

        【讨论】:

          猜你喜欢
          • 2013-11-15
          • 2015-08-27
          • 1970-01-01
          • 1970-01-01
          • 2015-05-28
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多