关于测试Angular$localize(Angular 9)的建议
回购示例 回购协议可以找到 请注意,这并不是一个完整的示例,它只是用来说明测试关于测试Angular$localize(Angular 9)的建议,angular,unit-testing,angular-i18n,Angular,Unit Testing,Angular I18n,回购示例 回购协议可以找到 请注意,这并不是一个完整的示例,它只是用来说明测试$localize的问题 有两个分支机构: 1. 主控 1. 启用本地化单元测试-这会更改测试.ts和polyfills.ts以防止导入@angular/localize/init,还监视$localize全局函数 概述 我已经将一个项目从Angular 8升级到了9(在之后),用Angular的新$localize功能(关于这方面的文档非常有限,这是我能找到的最好的)替换了该服务的任何用法(来自ngx transla
$localize
的问题
有两个分支机构:
1. <代码>主控
1. 启用本地化单元测试
-这会更改测试.ts
和polyfills.ts
以防止导入@angular/localize/init
,还监视$localize
全局函数
概述
我已经将一个项目从Angular 8升级到了9(在之后),用Angular的新$localize
功能(关于这方面的文档非常有限,这是我能找到的最好的)替换了该服务的任何用法(来自ngx translation/i18n polyfill)。我可以运行本地化的构建并再次在特定的区域设置中为应用程序提供服务。然而,在单元测试方面,我遇到了一些障碍
以前,当使用i18n polyfill
时,可以将i18n
服务注入组件等,如下所示(请参阅):
@组件({
选择器:“app-i18-polyfill”,
模板:`{title}}
})
导出类I18nPolyfillComponent{
只读标题:string=this.i18n({
id:“头衔”,
价值观:“你好,世界!”
});
构造函数(私有i18n:i18n){}
}
这可以通过向组件中注入间谍来轻松测试:
description(“I18nPolyfillComponent”,()=>{
let组件:I18nPolyfillComponent;
let夹具:组件夹具;
让mockI18n:间谍;
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[I18nPolyfillComponent],
供应商:[
{
提供:I18n,
useValue:jasmine.createSpy(“I18n”),
},
],
})
.compileComponents()。然后(()=>{
mockI18n=TestBed.inject(I18n)作为Spy;
});
}));
在每个之前(()=>{
fixture=TestBed.createComponent(I18nPolyfillComponent);
组件=fixture.componentInstance;
mockI18n.and.callFake((def:I18nDef)=>def.value);
});
它(“应该调用i18n一次”,()=>{
期望(模拟18n)。被催促的时间(1);
});
});
但是,我不确定是否可以编写类似的单元测试来测试$localize
的使用,因为它是一个全局函数,而不是一个可注入的服务
为确保完整性,使用$localize
(请参阅)组件将如下所示:
@组件({
选择器:“app-i18n-localize”,
模板:`{title}}
})
导出类I18nLocalizeComponent{
只读标题:字符串=$localize`:@@title:Hello World!`;
}
测试原理
我希望确保我的应用程序与I18n
/$localize
进行适当的交互(调用正确的次数,使用正确的参数等)。这只是为了防止在有人意外更改trans unit ID或基本转换值时出现愚蠢的错误
我尝试过的
我已尝试在test.ts
中用间谍替换全局$localize
函数,并避免导入@angular/localize/init
:
import Spy=jasmine.Spy;
导入createSpy=jasmine.createSpy;
const\u global:any=typeof global!==“未定义”和“全局”;
_全局.$localize=createSpy($localize”);
宣布全球{
const$本地化:间谍;
}
然后在测试中使用spied$localize
(请参阅:
description(“I18nLocalizeComponent”,()=>{
let组件:I18nLocalizeComponent;
let夹具:组件夹具;
让mockI18n:间谍;
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[I18nLocalizeComponent],
})
.compileComponents();
}));
在每个之前(()=>{
$localize.calls.reset();
$localize.and.returnValue(“你好,世界!);
fixture=TestBed.createComponent(I18nLocalizeComponent);
组件=fixture.componentInstance;
});
它(“应该调用$localize一次”,()=>{
预计($localize)。已被催收时间(1);
});
});
spy确实可以工作,但如果组件或其他组件在其模板中使用i18n
指令,测试将失败,例如():
知识产权保护,保护精英
此操作将失败,并出现以下错误:
TypeError: Cannot read property 'substr' of undefined
at <Jasmine>
at removeInnerTemplateTranslation (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:34560:1)
at getTranslationForTemplate (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:34582:1)
at i18nStartFirstPass (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:34771:1)
at ɵɵi18nStart (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:34718:1)
at ɵɵi18n (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:35450:1)
at I18nLocalizeTemplateComponent_Template (ng:///I18nLocalizeTemplateComponent.js:15:9)
at executeTemplate (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:11949:1)
at renderView (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:11735:1)
at renderComponent (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:13244:1)
at renderChildComponents (http://localhost:9877/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:11538:1)
Error: Expected undefined to be truthy.
at <Jasmine>
at UserContext.<anonymous> (http://localhost:9877/_karma_webpack_/src/app/i18n-localize-template/i18n-localize-template.component.spec.ts:23:23)
at ZoneDelegate.invoke (http://localhost:9877/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9877/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:292:1)
4.4.1
)和Jasmine(3.5.9
)进行单元测试 _ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.0.6
Node: 13.2.0
OS: darwin x64
Angular: 9.0.6
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes
Package Version
------------------------------------------------------------
@angular-devkit/architect 0.900.6
@angular-devkit/build-angular 0.900.6
@angular-devkit/build-ng-packagr 0.900.6
@angular-devkit/build-optimizer 0.900.6
@angular-devkit/build-webpack 0.900.6
@angular-devkit/core 9.0.6
@angular-devkit/schematics 9.0.6
@angular/cdk 9.1.3
@ngtools/webpack 9.0.6
@schematics/angular 9.0.6
@schematics/update 0.900.6
ng-packagr 9.0.3
rxjs 6.5.4
typescript 3.7.5
webpack 4.41.2
我找到的解决方案是监视
$localize
的translate
功能,而不是$localize
本身:
测试.ts
const\u global:any=typeof global!=“未定义”&&global;
const defaultFakedLocalizeTranslate:(messageParts:TemplateStringsArray,
替换:只读任何[])=>[TemplateStringsArray,只读任何[]]=
(messageParts:TemplateStringsArray,替换:只读任何[])=>[messageParts,替换];
_global.mockLocalize=createSpy(“mockLocalize”)作为Spy;
宣布全球{
const mock本地化:间谍;
}
$localize.translate=mockLocalize.and.callFake(defaultFakedLocalizeTranslate);
确保已在test.ts
中导入@angular/localize/init
I18nLocalizeComponent
单元测试可以更新如下:
description('I18nLocalizeComponent',()=>{
let组件:I18nLocalizeComponent;
let夹具:组件夹具;
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[I18nLocalizeComponent],
})
.compileComponents();
}));
在每个之前(()=>{
mockLocalize.calls.reset();
fixture=TestBed.createComponent(I18nLocalizeComponent);
组件=fixture.componentInstance;
});
应该是