【问题标题】:How to mock a module API dependency in Jasmine unit test?如何在 Jasmine 单元测试中模拟模块 API 依赖项?
【发布时间】:2018-06-28 19:56:44
【问题描述】:

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

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

  1. 首先 beforeEach 创建了一个符合 this guide 的依赖模拟 并注册了myApp 模块以使用angular.mock.module 进行测试。
  2. 然后在第二个 beforeEach 中使用 $injector 将模拟的 FuzzAPI 传递给 myApp 指令的 $compile 步骤。

但即使在模拟了依赖项之后,我也会收到一个$injector:modulerr 告诉我 services.FuzzAPI 不可用。 这告诉我,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
    };
  }
})();

//my-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
  }));


});

【问题讨论】:

    标签: angularjs unit-testing dependency-injection jasmine


    【解决方案1】:

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

    表示应该模拟的是services.FuzzAPI module,而不是service。根据提供的代码,服务名称是FuzzAPI,应该用构造函数模拟,而不是object

    为了使丢失的模块不会导致错误,应该将其存根。它可以被存根一次,在顶级 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 间谍作为模拟/存根函数。

    【讨论】:

      猜你喜欢
      • 2013-07-07
      • 2017-09-25
      • 2012-07-11
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 2020-03-29
      相关资源
      最近更新 更多