当前位置: 首页 > 面试题库 >

如何在AngularJS Jasmine单元测试中模拟返回承诺的服务?

江俊能
2023-03-14
问题内容

我有myService使用myOtherService,它可以进行远程调用,并返回promise:

angular.module('app.myService', ['app.myOtherService'])
  .factory('myService', [
    myOtherService,
    function(myOtherService) {
      function makeRemoteCall() {
        return myOtherService.makeRemoteCallReturningPromise();
      }

      return {
        makeRemoteCall: makeRemoteCall
      };      
    }
  ])

要对myService我进行单元测试,需要模拟myOtherService,以便其makeRemoteCallReturningPromise方法返回promise。这是我的方法:

describe('Testing remote call returning promise', function() {
  var myService;
  var myOtherServiceMock = {};

  beforeEach(module('app.myService'));

  // I have to inject mock when calling module(),
  // and module() should come before any inject()
  beforeEach(module(function ($provide) {
    $provide.value('myOtherService', myOtherServiceMock);
  }));

  // However, in order to properly construct my mock
  // I need $q, which can give me a promise
  beforeEach(inject(function(_myService_, $q){
    myService = _myService_;
    myOtherServiceMock = {
      makeRemoteCallReturningPromise: function() {
        var deferred = $q.defer();

        deferred.resolve('Remote call result');

        return deferred.promise;
      }    
    };
  }

  // Here the value of myOtherServiceMock is not
  // updated, and it is still {}
  it('can do remote call', inject(function() {
    myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
      .then(function() {
        console.log('Success');
      });    
  }));

从上面可以看到,我的模拟的定义取决于$q,我必须使用来加载inject()。此外,应该在中进行注入模拟module(),这应该在之前进行inject()。但是,更改模拟后,其值不会更新。

正确的方法是什么?


问题答案:

我不确定为什么您的方法不起作用,但是我通常使用该spyOn函数来完成。像这样:

describe('Testing remote call returning promise', function() {
  var myService;

  beforeEach(module('app.myService'));

  beforeEach(inject( function(_myService_, myOtherService, $q){
    myService = _myService_;
    spyOn(myOtherService, "makeRemoteCallReturningPromise").and.callFake(function() {
        var deferred = $q.defer();
        deferred.resolve('Remote call result');
        return deferred.promise;
    });
  }

  it('can do remote call', inject(function() {
    myService.makeRemoteCall()
      .then(function() {
        console.log('Success');
      });    
  }));

还要记住,您将需要$digest调用要调用的then函数。请参阅$q文档的“ 测试”部分。

- - - 编辑 - - -

在仔细查看您在做什么之后,我认为我在您的代码中看到了问题。在中beforeEach,您将设置myOtherServiceMock为一个新对象。将$provide永远不会看到这个参考。您只需要更新现有参考:

beforeEach(inject( function(_myService_, $q){
    myService = _myService_;
    myOtherServiceMock.makeRemoteCallReturningPromise = function() {
        var deferred = $q.defer();
        deferred.resolve('Remote call result');
        return deferred.promise;   
    };
  }


 类似资料:
  • 问题内容: 在Angular中,所有内容似乎都具有陡峭的学习曲线,并且对Angular应用程序进行单元测试绝对不能逃脱这种范例。 当我开始使用TDD和Angular时,我觉得我花了两倍(可能更多)的时间来弄清楚如何测试,甚至花更多的时间来正确地设置测试。但是正如Ben Nadel 在他的博客中所说的那样,角度学习过程存在起伏。他的图表绝对是我在Angular的经历。 但是,随着我在学习Angula

  • 问题内容: 根据Michal Charemza帖子编辑。 我有一个代表angularui模态对话框的服务: 如果用户单击对话框中的“确定”,则在调用delete方法时将执行。 问题是我无法对此进行单元测试。 这是我的考验。我已经正确注入了q服务,但是我不确定应该从间谍那里返回什么… 但是我正在接受。这意味着…部分没有执行。我想念什么? 问题答案: 要模拟返回承诺的函数,它还需要返回承诺,然后需要将

  • 问题内容: 我有使用,它可以进行远程调用,并返回promise: 要对我进行单元测试,需要模拟,以便其方法返回promise。这是我的方法: 从上面可以看到,我的模拟的定义取决于,我必须使用进行加载。此外,应该在中进行注入模拟,这应该在之前进行。但是,更改模拟后,其值不会更新。 正确的方法是什么? 问题答案: 我不确定为什么您的方法行不通,但是我通常使用该函数来完成。像这样: 还要记住,您将需要调

  • 问题内容: 关于这两个重要来源:NZakas- 承诺链中的归还承诺 和MDN承诺,我想提出以下问题: 每次我们从承诺履行处理程序返回值时,该值如何传递给从同一处理程序返回的新承诺? 例如, 在这个例子中,是一个承诺。也是来自履行处理程序的承诺。但是。取而代之的是神奇地解决(如何?),然后将该值传递给的实现处理程序。即使是这里的句子也令人困惑。 您能给我解释一下这到底是怎么回事吗?我对这个概念感到困

  • 问题内容: 我正在尝试编写业力/茉莉花测试,我想对模拟如何在正在返回诺言的服务上工作进行一些解释。我解释一下我的情况: 我有一个控制器,在其中执行以下调用: 这是我的服务方式: 最后,这是我的单元测试: 我真正想做的是将响应对象({“ elements:…})作为fillMapDatas函数的datas参数。我不了解如何模拟所有服务内容(服务,承诺,然后) 问题答案: 因此,如果您的服务是否按预期

  • 问题内容: 我的控制器具有如下代码: 在我的单元测试中,我正在做这样的事情: 现在在测试中,我正在检查是否调用了服务,并且data1,data2是否未定义。 我的问题是,这是工作的罚款,直到我取代与q.all控制器和测试我个人的服务电话与。使用q.all和(也尝试使用),两个测试均失败,并显示以下错误: 达到10个$ digest()迭代。流产! 如果我删除了,那么承诺永远不会得到解决,而测试失败