Angularjs 如何在我的角度单元测试中模拟服务的依赖关系?

Angularjs 如何在我的角度单元测试中模拟服务的依赖关系?,angularjs,unit-testing,karma-runner,karma-mocha,Angularjs,Unit Testing,Karma Runner,Karma Mocha,我用的是因果报应、棱角分明和摩卡咖啡 我要注入的MyServices模块。它的addThing方法还调用$localStorage提供程序,我想测试$localStorage.setItem方法在调用MyServices.addThing(data) 这是我的密码: describe('MyServices', function() { var $q; var $rootScope; var $scope; var MyServices; var $timeout; va

我用的是因果报应、棱角分明和摩卡咖啡

我要注入的
MyServices
模块。它的
addThing
方法还调用
$localStorage
提供程序,我想测试
$localStorage.setItem
方法在调用
MyServices.addThing(data)

这是我的密码:

describe('MyServices', function() {
  var $q;
  var $rootScope;
  var $scope;
  var MyServices;
  var $timeout;
  var $httpBackend;

  // inject modules
  beforeEach(function(){
    module('my.stuff');

    var _LocalStorage_ = {
      setItem: function(){
        return 'foo';
      }
    };

    // mock the dependencies of the module we are testing
    module(function ($provide) {
      $provide.value('$localStorage', _LocalStorage_); //here is where the error occurs
    });
  });

  beforeEach(inject(function (_$q_, _$rootScope_, _$timeout_, _MyServices_, _$httpBackend_) {
    $q = _$q_;
    $rootScope = _$rootScope_;
    $timeout = _$timeout_;
    MyServices = _MyServices_;
    $httpBackend = _$httpBackend_;
    $scope = $rootScope.$new();
  }));

  it.only('should call a method and access localStorage', function(){
    var spyAdd = sinon.spy(MyServices, 'addThing');
    var spySetItem = sinon.spy($localStorage, 'setItem');

    MyServices.addThing({ name: 'Thing' });

    expect(spyAdd.callCount).to.equal(1);
    expect(spySetItem.callCount).to.equal(1);
  })
});

当我运行它时,我得到一个错误,
$localStorage
未定义。

您没有注册那个假的$localStorage,只需使用原始的$localStorage并在setItem方法上创建一个spy

所以去掉这个

var _LocalStorage_ = {
  setItem: function(){
    return 'foo';
  }
};
module(function ($provide) {
  $provide.value('$localStorage', _LocalStorage_); //here is where the error occurs
});
但是在这里注射

var $localStorage;
beforeEach(inject(function (_$q_, _$rootScope_, _$timeout_, _MyServices_, _$httpBackend_, _$localStorage_) {
  $q = _$q_;
  $rootScope = _$rootScope_;
  $timeout = _$timeout_;
  MyServices = _MyServices_;
  $httpBackend = _$httpBackend_;
  $scope = $rootScope.$new();
  $localStorage = _$localStorage_; //here
}));

由于您已经在该方法上创建了一个spy,因此在测试中不需要更改任何内容。

您没有注册该伪$localStorage,只需使用原始的$localStorage并在setItem方法上创建一个spy即可

所以去掉这个

var _LocalStorage_ = {
  setItem: function(){
    return 'foo';
  }
};
module(function ($provide) {
  $provide.value('$localStorage', _LocalStorage_); //here is where the error occurs
});
但是在这里注射

var $localStorage;
beforeEach(inject(function (_$q_, _$rootScope_, _$timeout_, _MyServices_, _$httpBackend_, _$localStorage_) {
  $q = _$q_;
  $rootScope = _$rootScope_;
  $timeout = _$timeout_;
  MyServices = _MyServices_;
  $httpBackend = _$httpBackend_;
  $scope = $rootScope.$new();
  $localStorage = _$localStorage_; //here
}));
由于您已经在该方法上创建了一个间谍,因此在测试中不需要更改任何内容。

请尝试在您的方法之外声明LocalStorage。顺便说一句,您不需要_,您可以称之为LocalStorage

我还建议下载,因为在监视或模拟依赖项时,它有一系列有用的方法。

在每次使用之前,请尝试在外部声明LocalStorage。顺便说一句,您不需要_,您可以称之为LocalStorage


我还建议下载,因为它在监视或模拟依赖项时有许多有用的方法。

它不可用于注入,因为它位于不同于MyServices注入的命名空间中。如果我加载名称空间,我将不得不模拟100件事情。所以我想用
$provide.value('$localStorage',myMock)
你说不同的名称空间是什么意思,比如在不同的模块中,只需尝试$provide.factory而不是$provide.value。我尝试了
$provide.factory
它说它不是$get函数。如果使用.factory,第二个参数应该是函数而不是对象$工厂('$localStorage',function(){return localStorage;});它不可用于注入,因为它位于与MyServices注入不同的命名空间中。如果我加载名称空间,我将不得不模拟100件事情。所以我想用
$provide.value('$localStorage',myMock)
你说不同的名称空间是什么意思,比如在不同的模块中,只需尝试$provide.factory而不是$provide.value。我尝试了
$provide.factory
它说它不是$get函数。如果使用.factory,第二个参数应该是函数而不是对象$工厂('$localStorage',function(){return localStorage;});