使用ngMock模拟服务单元测试$ HTTP调用 [英] Using ngMock to simulate $http calls in service unit tests

查看:144
本文介绍了使用ngMock模拟服务单元测试$ HTTP调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找这几个小时。我的例子后尝试的例子。我只是似乎无法得到这个工作。请帮助=)

I've been looking at this for hours. I've tried example after example. I just can't seem to get this to work. Please help =)

我做的这一切对角种子回购干净的克隆(GIT://github.com/angular/angular-seed.git)。我做了,除了下面列出的任何更改。

I am doing all this on a clean clone of the angular-seed repo (git://github.com/angular/angular-seed.git). I have made no changes except those listed below.

当我运行下面的测试工作。请注意,在这个版本中,服务做任何类型的$ HTTP调用之前返回一个值。

When I run the following, the test works. Note that in this version, the service returns a value before doing any kind of $http call.

./应用/ JS /服务/ services.js

'use strict';
angular.module('myApp.services', [])
  .factory("exampleService", function ($http) {
    return {value:"goodValue"};

    $http.get("/exampleUrl")
      .success(function () {
        return {value:"goodValue"};
      })
      .error(function () {
        return {value:"badValue"};
      })
  });

./测试/单位/ servicesSpec.js

'use strict';
describe('service', function() {
  var $httpBackend;

  beforeEach(module('myApp.services'));

  beforeEach(inject(function ($injector) {
    $httpBackend = $injector.get("$httpBackend");
    $httpBackend.when("GET", "/exampleUrl")
      .respond({value:"goodValue"});
  }));

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

  describe('exampleService', function () {
    it('.value should be "goodValue"', inject(function (exampleService) {
      expect(exampleService.value).toEqual("goodValue");
    }));
  });
});

结果

info (watcher): Changed file "/home/username/mocktest/test/unit/servicesSpec.js".
Chrome 26.0: Executed 5 of 5 SUCCESS (0.136 secs / 0.035 secs)

当我删除行 {返回值:goodValue}; 实际上让它运行 $ http.get(),整个事情打破了以下错误:

When I remove the line return {value:"goodValue"}; and actually let it run the $http.get(), the whole thing breaks with the following errors:

info (watcher): Changed file "/home/username/mocktest/app/js/services.js".
Chrome 26.0 service exampleService .value should be "goodValue" FAILED
  TypeError: Cannot read property 'value' of undefined
      at null.<anonymous> (/home/username/mocktest/test/unit/servicesSpec.js:22:28)
      at Object.invoke (/home/username/mocktest/app/lib/angular/angular.js:2864:28)
      at workFn (/home/username/mocktest/test/lib/angular/angular-mocks.js:1758:20)
  Error: Declaration Location
      at window.jasmine.window.inject.angular.mock.inject (/home/username/mocktest/test/lib/angular/angular-mocks.js:1744:25)
      at null.<anonymous> (/home/username/mocktest/test/unit/servicesSpec.js:21:40)
      at null.<anonymous> (/home/username/mocktest/test/unit/servicesSpec.js:20:3)
      at /home/username/mocktest/test/unit/servicesSpec.js:4:1
  Error: Unflushed requests: 1
      at Error (<anonymous>)
      at Function.$httpBackend.verifyNoOutstandingRequest (/home/username/mocktest/test/lib/angular/angular-mocks.js:1225:13)
      at null.<anonymous> (/home/username/mocktest/test/unit/servicesSpec.js:17:18)
Chrome 26.0: Executed 5 of 5 (1 FAILED) (0.14 secs / 0.043 secs)

的思考

我的犯罪嫌疑人的我需要做一些在服务承诺的对象返回,那么解决它之后,但我不知道这将是。任何帮助AP preciated。

Thoughts

I suspect I need to do some kind of returning of a promise object in the service, then resolve it afterwards, but I have no idea what that would be. Any help appreciated.

推荐答案

您怀疑的解决办法是在正确的轨道上 - 的承诺是关键,以固定的错误/失败测试

Your suspected solution was on the right track - promises were the key to fixing the errors/failing tests.

使用原始 $ HTTP 服务,有条件返回工厂对象没工作,因为你得到了有效返回的没有的从你的工厂函数(由于异步承诺分辨率 $ HTTP )。

Using your original $http service to conditionally return the factory object didn't work because you were effectively returning nothing from your factory function (due to the asynchronous promise resolution of $http).

我认为只是把收益在原始 $ http.get()呼叫的前面。但是,这并不是所期望的行为,因为AngularJS .factory 方法应该返回您定义的服务对象,而不是由调用返回的<$ C $的轻率承诺C> $ HTTP 。

I considered just putting return in front of your original $http.get() call. But that isn't the desired behavior, because the AngularJS .factory method should return a service object that you define, not an mere promise returned by the call to $http.

该解决方案暴露,可以通过你的应用程序中调用你的 exampleService 对象的方法。这的getData()方法返回一个承诺(通过 $ HTTP ),您的应用/测试可以异步使用处理 .success() .error()

The solution is exposing a method on your exampleService object that can be called by your app. That getData() method returns a promise (via $http) which your app/test can handle asynchronously using .success() or .error()

./应用/ JS /服务/ services.js

'use strict';
angular.module('myApp.services', [])
    .factory("exampleService", function ($http) {
        return {
            getData: function () {
                return $http.get("/exampleUrl");
            }
        }
  });

./测试/单位/ servicesSpec.js

'use strict';
describe('service', function() {
  var $httpBackend;

  beforeEach(module('myApp.services'));

  beforeEach(inject(function ($injector) {
    $httpBackend = $injector.get("$httpBackend");
    $httpBackend.when("GET", "/exampleUrl")
        .respond(200, {value:"goodValue"});
  }));

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

  describe('exampleService successful http request', function () {
    it('.value should be "goodValue"', inject(function (exampleService) {

        exampleService.getData().success(function(response) {
          expect(response.value).toEqual("goodValue");
        }).error( function(response) {
          //should not error with $httpBackend interceptor 200 status
          expect(false).toEqual(true);
        });

    }));
  });


});

注意的Destron的约 $ httpBackend.flush()意见也很重要,以获得模拟后台拦截 $ http.get() 从您的服务请求。

Note that Destron's comment about $httpBackend.flush() was also important to get the mock backend to intercept the $http.get() request from your service.

希望有所帮助。

这篇关于使用ngMock模拟服务单元测试$ HTTP调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆