【问题标题】:Unable to use httpBackend flush for ngMockE2E无法为 ngMockE2E 使用 httpBackend 刷新
【发布时间】:2016-04-05 15:38:16
【问题描述】:

我正在尝试使用 jasmine 测试我的控制器。基本上,当控制器被创建时,它会调用一个服务来发出 http 请求。我正在使用 httpBackend 来获取假数据。当我尝试运行测试时,我总是收到错误“没有待处理的刷新请求”。如果我删除 httpBackend.flush() 则测试失败,因为 controller.data.name 未定义。谁能知道为什么会这样?谢谢。

模块的代码在这里:

var myModule = angular.module('myModule', ['ngMockE2E']);
myModule.run(function($httpBackend){
  $httpBackend.whenGET('/Person?content=Manager').respond(function (){
     var response = {'name':'Bob','age':'43'}
     return [200,response];
  })
});

服务代码:

myModule.factory('myService',function($http){
     return {
        getData: function(position){
             return  $http.get('/Person?content='+position); 
        }
     }
});

控制器的代码是:

myModule.controller('myController',function(xrefService){
    var _this = this;
    _this.data ={};
    _this.getData = function(position){
        myService.getData(position).then(function(response){
            _this.data = response.data
        });
    }
    _this.getData("Manager");
})

测试控制器的代码是:

describe("Test Controller",function(){
   var controller,httpBackend,createController;
   beforeEach(module('myModule'));
   beforeEach(inject(function($controller,$httpBackend){      
      createController = function(){
         return $controller('myController');
      }
      httpBackend = $httpBackend;     
   }));
   it("should return data",function(){
      controller = createController();
      httpBackend.flush();
      expect(controller.data.name).toEqual("Bob");
   });      
})

【问题讨论】:

    标签: angularjs karma-jasmine httpbackend ngmocke2e


    【解决方案1】:

    angular documentation 对 ngMockE2E 的 $httpbackend 进行了以下说明:

    此外,我们不希望手动刷新模拟出来 像我们在单元测试期间所做的那样的请求。出于这个原因,e2e $httpBackend 自动、紧密地刷新模拟请求 模拟 XMLHttpRequest 对象的行为。

    所以,简短的回答:它不存在,你也不需要它。

    【讨论】:

      【解决方案2】:

      您在“模块代码”中使用 $httpBackend.whenGET

      您应该在测试代码中使用 $httpBackend,如下所示...

      it("should return data",function(){
        $httpBackend.expectGET('/Person?content=Manager').respond(function (){
            var response = {'name':'Bob','age':'43'}
            return [200,response];
        })
        controller = createController();
        httpBackend.flush();
        expect(controller.data.name).toEqual("Bob");
      });      
      

      我也建议使用 expectGET 而不是 whenGET。

      使用 whenGET 你是说如果请求被发出然后响应像这样。

      使用 expectGET 你是说......将发出一个请求,当它做出这样的响应时,如果没有发出请求,则测试失败。

      PS 如果您在控制器代码中放置了一些 console.log 语句,那么您应该在运行测试套件时看到这些日志语句。如果没有,那么您知道您的控制器代码甚至没有被命中。

      也用..

      afterEach(function () {
            httpBackend.verifyNoOutstandingExpectation();
            httpBackend.verifyNoOutstandingRequest();
      });
      

      如果没有达到预期,这将强制测试失败。

      【讨论】:

      • 感谢 danday74,它现在可以工作了。但是我想知道是否可以避免在测试方法中使用 expectGET().respond() 。因为这意味着我需要阅读服务代码来测试控制器。例如,也许我只想测试 controller.data 是否不为空(这意味着它从后端接收了一些数据)。
      • 现在你在想 :) 是的,你想使用 Jasmine 间谍。 ng-learn.org/2014/08/Testing_Promises_with_Jasmine_Provide_Spy.
      • spyOn(myService, 'getData').and.callFake(function() { var def = $q.defer(); def.resolve(YOUR_MOCK_HTTP_RESPONSE); return def.promise; });期望(myService.getData).toHaveBeenCalled();
      • 代码说......当 myService.getData() 被调用时,然后以假响应响应。假响应返回一个承诺,就像你的真实方法返回一个承诺一样。然后你可以监视你的服务函数,看看它被调用了多少次,它被调用的参数等等。你可以继续检查 controller.data 中的值 no probs - 现在将由你的假数据填充在您的虚假回复中提供。上帝保佑 :) 忘了提一下,你真正的 HTTP 现在不会被调用,所以你不需要再期待GET了。
      • 感谢 danday74,它真的很有帮助。 :D
      猜你喜欢
      • 2013-06-03
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 2023-03-22
      相关资源
      最近更新 更多