如何进行单元测试与茉莉外部依赖一个ngcontroller? [英] how to unit test a ngcontroller with external dependencies in jasmine?

查看:174
本文介绍了如何进行单元测试与茉莉外部依赖一个ngcontroller?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个因缘单元测试的angularcontroller,这是控制器。使用从这里一个FileUpload( https://github.com/nervgh/angular-file-upload

  VAR C,迪;C =功能($范围,FileUploader,UploadHelper,的currentUser){
  VAR上传;  $ scope.uploader =上传=新FileUploader(UploadHelper.getOptions());  uploader.onSuccessItem =函数(项目,响应状态,报头){
    //做一点事
  };
  返回此;
};迪='$范围,FileUploader','UploadHelper','的currentUser',C]。angular.module('mycontrollers')控制器('DocumentsController',二)。

我的茉莉花测试看起来是这样的:

 描述(客户:控制器:DocumentsController',函数(){
  变量$ rootScope,DocumentMock,UserMock,documentsController,范围;
  documentsController = $ rootScope = =范围= DocumentMock UserMock = NULL;  beforeEach(函数(){
    模块(mycontrollers);
    回注入(函数($控制器,_ $ rootScope_,$ Q){
      VAR推迟,文件,fileUploader,uploadHelper,用户;
      $ rootScope = _ $ rootScope_;
      范围= $ rootScope $新的()。
      文件= [
        {
          ID:DOC 1
          documentType:其他
        },{
          ID:DOC 2
          documentType:PDF
        },{
          ID:DOC 3
          五:PDF
        }
      ];
      用户= {
        ID:'USER_ID',
        用户名:用户名
      };
      UserMock = {
        的currentUser:功能(){
          返回用户;
        }
      };
      fileUploader = {};
      uploadHelper = {};      返回documentsController = $控制器('DocumentsController',{
        文件:文件,
        $适用范围:适用范围,
        FileUploader:fileUploader,
        UploadHelper:uploadHelper,
        的currentUser:UserMock      });
    });
  });
  返回描述(关于创建功能(){
    返回它(应该指定文件范围功能(){
      返回期望(1).toEqual(1);
    });
  });
});

我有一种名为QuestionsAttachments其中有几个依赖关系:

  S =函数(API,$ HTTP,$ Q $超时){
  VAR QuestionsAttachments;
  返回QuestionsAttachments =(函数(){
    功能QuestionsAttachments(数据){
      angular.extend(此,数据);
    }    QuestionsAttachments [新] =功能(数据){
      返回新QuestionsAttachments(数据);
    };    返回QuestionsAttachments;  })();
};DI = ['API,$ HTTP,$ Q','$超时',S]。

这问题就是:我怎么能模拟出的API,$ HTTP,$ Q $超时

这是一个plunkr的链接:
http://plnkr.co/edit/BT8SJgW6ejcPw6xo1cpI?p=$p$pview


解决方案

  

基本上,你要做的就是建立一个窥视的,该方法
  服务。
  所有你所要做的就是让injetable服务(真正落实)
  而只是模拟/存根功能(S),你需要。无需创建自己的
  模仿对象,像这样: uploadHelper = {}

  spyOn(uploadHelper,'getOptions')。andCallFak​​e(函数(){
    //这里返回数据
});//或者你可以使用.Return({/ *一些对象* /})

您可以阅读更多关于茉莉和间谍特别这里


随着中说,我必须说,所提供的code的确看起来有点不完整的。
例如,所提供的样品你没有模块创建和您正在使用的getter语法,而不是直接的angular.module('mycontrollers',[]);

其次在测试你想你的控制器化期间注入文件,但这决不会工作,因为你没有注射参数的文件在您的控制器的定义。

所以问题您的遭遇可能是由于上述概述

不管怎么说,一个完整的例子,并把重点放在如何嘲笑的UploadHelper.getOptions /存根/间谍()可能是这个样子。而这里的工作Plunkr http://plnkr.co/edit/RfQFsaLq8XV2FvMT3xr0?p=preVIEW

实施

 
    .module('mycontrollers',[])
    .controller('DocumentsController',documentsController);    。documentsController $注射='$范围,FileUploader','UploadHelper','的currentUser'];    功能documentsController($范围,FileUploader,UploadHelper,的currentUser){
        VAR上传;        $ scope.uploader =上传=新FileUploader(UploadHelper.getOptions());        uploader.onSuccessItem =函数(项目,响应状态,报头){
            // 做一点事
        };
    }

测试

 描述(客户:控制器:DocumentsController',函数(){
    beforeEach(函数(){
        模块('mycontrollers');        注(函数($喷油器){
            //获取我们的依赖
            这$控制器= $ injector.get('$控制器');
            this.FileUploader = $ injector.get('FileUploader');
            this.UploadHelper = $ injector.get('UploadHelper');
            这$范围= $ injector.get('$ rootScope')美元的新()。
            this.user = {
                ID:'USER_ID',
                用户名:用户名
            };
            this.UserMock = {
                的currentUser:功能(){
                    返回用户;
                }
            }
        });
    });    功能initController(上下文){
        返回上下文。$控制器('DocumentsController',{
                $范围:环境$范围,
                FileUploader:context.FileUploader,
                UploadHelper:context.UploadHelper,
                的currentUser:context.UserMock
            });
    }    描述(论创作,函数(){
        它('应该调用UploadHelper.getOptions()',函数(){
            无论我们指定的getOptions //间谍,当它获取调用,回报
            spyOn(this.UploadHelper,'getOptions')andReturn({/ *某些选项* /});            //实例控制器
            initController(本);            期待(this.UploadHelper.getOptions).toHaveBeenCalled();
            期待(这$ scope.uploader.onSuccessItem).toBeDefined();
        });
    });
});

I am trying to write a karma unit test for a angularcontroller, this is the controller. Using a fileupload from here (https://github.com/nervgh/angular-file-upload):

var c, di;

c = function($scope, FileUploader, UploadHelper, currentUser) {
  var uploader;

  $scope.uploader = uploader = new FileUploader(UploadHelper.getOptions());

  uploader.onSuccessItem = function(item, response, status, headers) {
    //do something
  };
  return this;
};

di = [ '$scope', 'FileUploader', 'UploadHelper', 'currentUser', c];

angular.module('mycontrollers').controller('DocumentsController', di);

My jasmine test looks like this:

describe('Customer: Controller: DocumentsController', function() {
  var $rootScope, DocumentMock, UserMock, documentsController, scope;
  documentsController = $rootScope = scope = DocumentMock = UserMock = null;

  beforeEach(function() {
    module("mycontrollers");
    return inject(function($controller, _$rootScope_, $q) {
      var deferred, documents, fileUploader, uploadHelper, user;
      $rootScope = _$rootScope_;
      scope = $rootScope.$new();
      documents = [
        {
          id: "doc 1",
          documentType: "other"
        }, {
          id: "doc 2",
          documentType: "pdf"
        }, {
          id: "doc 3",
          v: "pdf"
        }
      ];
      user = {
        id: 'user_id',
        username: 'username'
      };
      UserMock = {
        currentUser: function() {
          return user;
        }
      };
      fileUploader = {};
      uploadHelper = {};

      return documentsController = $controller('DocumentsController', {
        documents: documents,
        $scope: scope,
        FileUploader: fileUploader,
        UploadHelper: uploadHelper,
        currentUser: UserMock

      });
    });
  });
  return describe("On creation", function() {
    return it("should assign documents to scope", function() {
      return expect(1).toEqual(1);
    });
  });
});

I got a service called QuestionsAttachments which has a few dependencies:

s = function(API, $http, $q, $timeout) {
  var QuestionsAttachments;
  return QuestionsAttachments = (function() {
    function QuestionsAttachments(data) {
      angular.extend(this, data);
    }

    QuestionsAttachments["new"] = function(data) {
      return new QuestionsAttachments(data);
    };

    return QuestionsAttachments;

  })();
};

di = ['API', '$http', '$q', '$timeout', s];

This questions is: how can I mock out the API ,$http, $q, $timeout ?

This is a link to a plunkr: http://plnkr.co/edit/BT8SJgW6ejcPw6xo1cpI?p=preview

解决方案

Basically what you do is you set up a spy on the method of that service. All you have to do is get the injetable service (the real implementation) and the just mock/stub the function(s) you need. No need to create your own mock objects like so: uploadHelper = {}

spyOn(uploadHelper, 'getOptions').andCallFake(function(){
    // return data here
});

// or you could use .Return({ /* some object */})

You can read more about jasmine and spies in particular here

With that said I must say that the code provided does look a bit incomplete. For instance, by the sample provided you have no module created and you are using the getter syntax directly instead of angular.module('mycontrollers', []);.

Secondly in your test you are trying to inject documents during instantiation of your controller but this will never work since you have no injectable argument 'documents' in your controller definition.

So the problem you are experince is likely due to the outlining above.

Anyways, A complete example, with the emphasis on how to mock/stub/spy on UploadHelper.getOptions() could look something like this. And here's a working Plunkr http://plnkr.co/edit/RfQFsaLq8XV2FvMT3xr0?p=preview

Implementation

angular
    .module('mycontrollers',[])
    .controller('DocumentsController', documentsController);

    documentsController.$inject = ['$scope', 'FileUploader', 'UploadHelper', 'currentUser'];

    function documentsController($scope, FileUploader, UploadHelper, currentUser){
        var uploader;

        $scope.uploader = uploader = new FileUploader(UploadHelper.getOptions());

        uploader.onSuccessItem = function(item, response, status, headers){
            // do something
        };
    }

Tests

describe('Customer: Controller: DocumentsController', function(){
    beforeEach(function(){
        module('mycontrollers');

        inject(function($injector){
            // fetch our dependencies
            this.$controller = $injector.get('$controller');            
            this.FileUploader = $injector.get('FileUploader');
            this.UploadHelper = $injector.get('UploadHelper');
            this.$scope = $injector.get('$rootScope').$new();
            this.user = {
                id: 'user_id',
                username: 'username'
            };
            this.UserMock = {
                currentUser: function(){
                    return user;
                }
            }
        });
    });

    function initController(context){
        return context.$controller('DocumentsController', {
                $scope: context.$scope,
                FileUploader: context.FileUploader,
                UploadHelper: context.UploadHelper,
                currentUser: context.UserMock
            });
    }

    describe('On creation', function(){
        it('should call UploadHelper.getOptions()', function(){
            // spy on getOptions and when it is getting called, return whatever we've specified
            spyOn(this.UploadHelper, 'getOptions').andReturn({ /* some options */});

            // instantiate the controller
            initController(this);

            expect(this.UploadHelper.getOptions).toHaveBeenCalled();
            expect(this.$scope.uploader.onSuccessItem).toBeDefined();
        });
    });
});

这篇关于如何进行单元测试与茉莉外部依赖一个ngcontroller?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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