模拟角度工厂使用

模拟角度工厂使用

本文介绍了模拟角度工厂使用$ Q在茉莉花的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这肯定已经问过,但我无法找到它。我需要模拟一个工厂,但模拟本身需要使用$ Q和我结束了一个鸡和蛋的情况与问候调用注射后模块()()

Surely this has been asked before but I can't find it. I need to mock a factory, but the mock itself needs to use $q, and I end up in a chicken and egg situation with regards to calling module() after inject().

我看着这个question该建议做一个spyOn,该工程的服务,因为它是一个单身,但我打电话由我厂返回功能,每次都创建一个新的实例,这样就不会工作...

I looked at this question which advises doing a spyOn, which works for services because it is a singleton, but I am calling new on the function returned by my factory, creating a new instance each time, so that won't work...

var app = angular.module('app', []);

app.factory('MyDependencyFactory', function() {
  return function() {
    this.doPromise = function () {
      var defer = $q.defer();
      //obviously more complicated.
      defer.resolve();
      return defer.promise;
    }
  }
});

app.factory('MyConsumingFactory', function(MyDependencyFactory) {
 return function() {
   var dependency = new MyDependencyFactory();
   this.result;

   this.doSomething = function () {
     dependency.doPromise().then(
       function (data) {
         this.result = data;
       },
       function (error) {
         console.log(error);
       }
       );
   }
  }
});

茉莉花测试:

describe('MyConsumingFactory', function() {
  var MyConsumingFactory;

  beforeEach(function () {
    module('app');

    inject( function (_MyConsumingFactory_) {
      MyConsumingFactory = _MyConsumingFactory_;
    });

    inject( function ($q) {
      mockMyDependencyFactory = function () {
        this.doPromise = function (data) {
            var defer = $q.defer();
            defer.resolve('mock data');
          };
        };
    });

    module( function ($provide) {
      $provide.factory('MyDependencyFactory', mockMyDependencyFactory);
    });
  });

  it('works correctly', function () {
    MyConsumingFactory.doSomething();
    $rootScope.$apply();
    expect(MyConsumingFactory.result).toEqual('mock data');
  });

});

我需要我的mockMyDependencyFactory使用$ Q,所以我需要把它包在注入(功能(... ,然后我需要调用的模块(函数之前做到这一点($提供){... 这当然给我:

I need my mockMyDependencyFactory to use $q, so I need to wrap it in inject( function(..., and I need to do this before the call to module( function ($provide) {... which of course give me:

错误:已创建的喷油器,无法注册模块

我如何避开这个问题有什么建议?

Any suggestions on how I get round this?

或者,如果你觉得我的设计有缺陷的(我想我可以实例化一个MyDependencyFactory并传递MyConsumingFactory化期间,而不是采用了棱角分明的DI吗?)我所有的耳朵:)

Or if you think my design flawed (I suppose I could instantiate a MyDependencyFactory and pass that during instantiation of MyConsumingFactory instead of using angular's DI?) I'm all ears :)

推荐答案

)首先,为模块的所有呼叫(前应注(),否则你会得到这个错误:喷油器已经创建,无法注册模块如您在注射之前应该注册模块!在code。知道了这一点,我们需要注射前嘲弄 MyDependencyFactory ,但我们怎样才能 $ Q 在那里,如果它只是在可注入()?实际上,它是在角测试的常用技术,以注射服务分配到一个测试套件一个全局变量,然后在所有情况下使用它:

First of all, all your calls to module() should be before inject(), otherwise you will get this error: Injector already created, can not register a module! i.e. you should register modules before you inject them in code. Knowing that, we need to mock MyDependencyFactory before injecting, but how do we get $q in there if it is only available in inject()? Actually, it is a common technique in angular tests, to assign injected service to a global variable in a test suite, and then use it across all scenarios:

describe('some suite', function () {

    // "global" variables for injected services
    var $rootScope, $q;

    beforeEach(function () {

        module('app');

        module(function($provide) {

            $provide.factory('MyDependencyFactory', function () {
                return function () {
                    this.doPromise = function (data) {
                        // use "globals"
                        var defer = $q.defer();
                        defer.resolve('mock data');
                        return defer.promise;
                    };
                };
            });

        });

        inject(function (_$rootScope_, _$q_) {
            // assign to "globals"
            $rootScope = _$rootScope;
            $q = _$q;
        });
    });

    // ....

});

您可以使用 $ Q 的原因 $提供块是它没有被立即使用,它会当你调用一个模拟的方法或创建一个嘲笑对象的实例只能使用。到那个时候,它会被注入并分配给全局变量 $ Q ,并有适当的值。

The reason you can use $q in a $provide block is that it is not being used immediately, it will be used only when you call a mocked method or create an instance of a mocked object. By that time, it will be injected and assigned to a global variable $q and have an appropriate value.

还有一招,如果你想用不同的值多次化解你的承诺,你可以做的,就是要创建一个全局变量延迟并初始化它里面没有具体的方法,但在某些 beforeEach 块,然后执行 defer.resolve('东西')用值的情况下,你里面想在这个特定的场景。

One more trick you could do if you want to resolve your promise with different values several times, is to create a global variable defer and initialize it not inside specific method, but in some beforeEach block, and then do defer.resolve('something') inside your scenario with a value you want in this particular scenario.

的工作示例,我做了一些额外的修复,使其工作(有评论)。

Here you can see a working example of your code, I've made some extra fixes to make it work (has comments).

请注意:我说的全局变量,但它不是一个特定的测试套件中实际上全球在JS术语,但全球

Note: I am saying "global" variable, but it is not actually global as in JS terminology, but global within a particular test suite.

这篇关于模拟角度工厂使用$ Q在茉莉花的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 19:23