如何在Jasmine单元测试中模拟模块API依赖?

时间:2018-01-19 14:35:05

标签: angularjs unit-testing dependency-injection jasmine

我有一个单元测试自定义Angular指令myApp的情况,并设置了必要的业力和茉莉配置。 在这个测试用例中,我试图模拟并存根myApp的依赖模块,即服务 - services.FuzzAPI。 因为我无法访问services.FuzzAPI文件来使用sinon来模拟它。

按照Angular和Jasmine文档,我在.spec文件中设置了我的规范文件并遵循此similar SO answer

  1. 在第一次之前,每个人都创建了一个依赖于this guide的依赖的模拟 并使用myApp注册angular.mock.module模块进行测试。
  2. 然后在第二个之前,每个人使用$ injector来传递那个模拟的FuzzAPI,用于myApp指令的$ compile步骤。
  3. 但即使在模拟了依赖项后,我得到一个$injector:modulerr告诉我services.FuzzAPI不可用。 这告诉我soemthing是services.FuzzAPI依赖注册的错过:

     LOG LOG: 'before mock'
     LOG LOG: 'after mock'
     Error: [$injector:modulerr] Failed to instantiate module myApp due to:
            Error: [$injector:modulerr] Failed to instantiate module services.FuzzAPI due to:
            Error: [$injector:nomod] Module 'services.FuzzAPI' is not available! You either misspelled the module name or forgot to load it
    

    问题:

    如何在Jasmine单元测试中模拟指令依赖?

    查看代码,我可以看到此错误正在行beforeEach(inject(function($rootScope, _$compile_, $injector) {上 因为在注入错误之前,注入beforeEach内的console.log没有被修改。

    指令和测试规范的要点:

    // my-app.js

    (function() {
    
      var component = {
        id: "myApp",
        name: "My App",
        templateUrl: localStorage.getItem("baseURL") + "my-app/my-app.html"
      };
    
      component.ui = angular.module("myApp", ["services.FuzzAPI"]);
      component.ui.directive("myApp", widgetComponent);
    
      function widgetComponent(FuzzAPI) {
    
        // main widget container
        function widgetContainer(scope, element, params) {
          var api = new FuzzAPI(params);
    
          scope.greeting = "Hello World";
    
          var setGreeting = function(message){
            scope.greeting = message;  
          };
    
          api.onDataEvent("onFuzzEvent", function(data) {
            scope.greeting = data;
          });
    
    
          element.on("$destroy", function() {     
            api.unregister();
            scope.$destroy();
          });
        }
    
        return {
          scope: {},
          replace: true,
          link: widgetContainer,
          templateUrl: component.templateUrl
        };
      }
    })();
    

    //我-app.spec.js

    describe("myApp", function() {
    
      var $scope, $compile, $provide, $injector, element, fuzzAPIMock, FuzzAPIProvider;
    
      beforeEach(function(){
    
        //mock service FuzzAPI via service provider
        fuzzAPIMock = {
          greeting : "123",
          initializeCurrentItem : function () {
            return true;
          }
        };
    
        console.log("before mock");
    
        //register module and mock dependency
        angular.mock.module(function($provide) {
                $provide.value('services.FuzzAPI', fuzzAPIMock);
        });
    
        angular.mock.module("myApp");
    
        console.log("after mock");
    
    
      });
    
      beforeEach(inject(function($rootScope, _$compile_, $injector) {
    
        console.log("in inject..");
        FuzzAPIProvider = $injector.get('services.FuzzAPI');
        $scope = $rootScope.$new(), //create instance of rootScope
        $compile = _$compile_; 
        console.log("in inject before compile..");
        element = $compile("<my-app></my-app>")($scope); // compile attaches directives to HTML template
        console.log("in inject after compile..");
        $scope.$digest(); //loop through DOM watchers, check values and trigger listeners
      }));
    
    
    });
    

1 个答案:

答案 0 :(得分:2)

  

错误:[$ injector:nomod]模块'services.FuzzAPI'不可用!您要么错误拼写了模块名称,要么忘记加载它

表示应该模拟services.FuzzAPI 模块,而不是服务。根据提供的代码,服务名称为FuzzAPI,应使用构造函数进行模拟,而不是对象

为了使丢失的模块不会导致错误,它应该是存根的。它可以在顶级describe块中存根一次:

beforeAll(() => {
  angular.module('services.FuzzAPI', []);
});

无法恢复存根模块(至少没有黑客攻击),但如果不在测试中显示真实模块,则不会出现问题。

然后可以照常模拟服务。如果是FuzzAPI:,则应为

fuzzAPIMock = jasmine.createSpy('').and.returnValue({
  greeting : "123",
  initializeCurrentItem : jasmine.createSpy('').and.returnValue(true)
});

angular.mock.module(function($provide) {
  $provide.value('FuzzAPI', fuzzAPIMock);
});

最好使用Jasmine间谍作为模拟/存根函数。