我怎么嘲笑,在Angularjs茉莉花单元测试返回承诺服务? [英] How do I mock a service that returns promise in Angularjs Jasmine unit test?

查看:120
本文介绍了我怎么嘲笑,在Angularjs茉莉花单元测试返回承诺服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用myOtherService,这使得远程调用,返回承诺为myService:

I have myService that uses myOtherService, which makes a remote call, returning promise:

angular.module('app.myService', ['app.myOtherService'])
  .factory('myService', [myOtherService,

    function(myOtherService) {
      function makeRemoteCall() {
        return myOtherService.makeRemoteCallReturningPromise();
      }

      return {
        makeRemoteCall: makeRemoteCall
      };      
    }
  ])

要做出为myService 单元测试,我需要模拟 myOtherService ,使得它的 makeRemoteCallReturningPromise()方法返回一个承诺。这就是我如何做到这一点:

To make a unit test for myService I need to mock myOtherService, such that its makeRemoteCallReturningPromise() method returns a promise. This is how I do it:

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 ,这是我用加载注入()。此外,注射模拟应该在模块发生(),应在来之前
注入()。但是,一旦我改变它没有更新的模拟值。

As you can see from the above, the definition of my mock depends on $q, which I have to load using inject(). Furthermore, injecting the mock should be happening in module(), which should be coming before inject(). However, the value for mock is not updated once I change it.

什么是做到这一点的正确方法?

What is the proper way to do this?

推荐答案

我不知道为什么你的方式没有它不工作,但我通常用 spyOn 的功能。事情是这样的:

I'm not sure why the way you did it doesn't work, but I usually do it with the spyOn function. Something like this:

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');
      });    
  }));

还记得,你需要做一个 $消化呼吁然后函数被调用。看到测试 $ Q文档的部分。

Also remember that you will need to make a $digest call for the then function to be called. See the Testing section of the $q documentation.

------ ------编辑

看着你在做什么更接近后,我觉得我看到你的code中的问题。在 beforeEach ,你设置 myOtherServiceMock 来一个全新的对象。在 $提供将再也看不到这个参考。你只需要更新现有的参考:

After looking closer at what you're doing, I think I see the problem in your code. In the beforeEach, you're setting myOtherServiceMock to a whole new object. The $provide will never see this reference. You just need to update the existing reference:

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

这篇关于我怎么嘲笑,在Angularjs茉莉花单元测试返回承诺服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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