单元测试使用承诺的角度控制器和服务? [英] Unit test an angular controller and service which uses a promise?

查看:106
本文介绍了单元测试使用承诺的角度控制器和服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法通过测试结果通过我使用非常基本的实现来更深入地了解测试。

I cannot get the test result to pass I'm using a very basic implementation to understand testing deeper.

我有一个工厂,它返回一个承诺,从我的控制器。我想测试调用成功并将响应分配给 repos var。以下是代码:

I have a factory which returns a promise, accessed from my controller. I want to test that the call succeeds and assigns the response to the repos var. Following is the code:

'use strict';

angular.module('app')
  .factory('searchServ', function ($timeout, $q, $http) {
    return {
      fetch: function(user) {
        var deferred = $q.defer();

        $timeout(function(){
          $http({method: 'GET', url: 'https://api.github.com/users/' + user + '/repos'}).then(function(repos) {
            deferred.resolve(repos.data);
          }, function(reason){
            deferred.reject(reason.status);
            console.log(reason);
          });
        }, 30);

        return deferred.promise;
      }
    };
  })
  .controller('MainCtrl', function ($scope, searchServ) {
    $scope.results = function(user) {
      $scope.message = '';
      searchServ.fetch(user).then(function (repos) {
        if(repos.length){
          $scope.message = '';
          $scope.repos = repos;
        }
        else{
          $scope.message = 'not found'
        }
      }, function (){
        $scope.message = 'not found';
      });
    };
  });

//Test

'use strict';

describe('MainCtrl', function () {
  var scope, searchServ, controller, deferred, repos = [{name: 'test'}];
  // load the controller's module
  beforeEach(module('app'));

  beforeEach(inject(function($controller, $rootScope, $q) {
    searchServ = {
      fetch: function () {
        deferred = $q.defer();
        return deferred.promise;
      }
    };
    spyOn(searchServ, 'fetch').andCallThrough();
    scope = $rootScope.$new();
    controller = $controller('MainCtrl', {
      $scope: scope,
      fetchGithub: fetchGithub
    });


  }));
  it('should test', function () {
    expect(scope.test).toEqual('ha');
  });

  it('should bind to scope', function () {
    scope.results();
    scope.$digest();
    expect(scope.message).toEqual('');
    //expect(scope.repos).not.toBe(undefined);
  });
});

运行测试时出现以下错误:

Running the test gives me the following error :


TypeError:undefined不是test / spec / controllers / main.js中的函数(评估'spyOn(searchServ,'fetch')。andCallThrough()') (第15行)

我知道如何测试它,以便它也测试范围绑定作为异步调用?

Any idea how I can test this such that it tests the scope binding as well as the async call?

推荐答案

您的代码存在很多问题。

There are a lot of issues with your code.

我已创建 此Plunkr 目的。 index.js 是包含您的代码和测试用例的文件。我根据惯例和最佳实践编辑了大部分内容。

I've created this Plunkr for the purpose. index.js is the file with your code and test cases. I've edited most of the part according to the conventions and best-practices.

我想给你一些指示:


  • 由于 $ http 返回一个承诺,你应该使用它,而不是解决承诺并从中创建另一个承诺你的方法。不知道为什么超时使用。所以我从 searchServ 中删除​​了 $ q $ timeout 依赖。

  • 我在测试用例中删除了您使用的 deferred 变量。

  • 您应该使用 angular-mocks.js 来模拟您的服务和其他依赖项,而不是在您的测试用例中定义服务(您的方式。 )

  • 您应该创建单独的 describe 块来测试代码的不同部分( controller 在这种情况下)。

  • Since $http returns a promise, you should use that, instead of resolving the promise and creating another promise from your method. Not sure why is timeout used. So I removed $q and $timeout from searchServ's dependencies.
  • I did the same in the test case by removing the deferred variable that you used.
  • You should be using angular-mocks.js to mock your services and other dependencies instead of defining a service inside your test case(The way you have did.)
  • You should create separate describe blocks for testing different parts of your code(a controller in this case).

希望这会有所帮助!

这篇关于单元测试使用承诺的角度控制器和服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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