如何在茉莉花单元测试中模拟模块 API 依赖?



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

按照 Angular 和 Jasmine 文档,我在.spec文件中设置了我的规范文件,并遵循这个类似的 SO 答案

  1. 在第一个之前每个都创建了适应本指南的迂腐的模拟 并注册了myApp模块以使用angular.mock.module进行测试。
  2. 然后在之前的第二秒,Each使用$injector通过模拟FuzzAPI$compilemyApp指令的步骤。

但即使在嘲笑依赖之后,我也得到了一个$injector:modulerr告诉我服务。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

问题:

你怎么能在茉莉花单元测试中模拟指令迂腐

?查看代码,我可以看到此错误正在在线抛出beforeEach(inject(function($rootScope, _$compile_, $injector) {作为控制台.log注入beforeEach内部在引发错误之前不会旋转。

指令和测试规范的要点:

我的应用程序.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
}));

});
错误:

[$injector:nomod] 模块'服务。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);
});

使用茉莉花间谍作为模拟/存根功能总是更可取的。

最新更新