Kam*_*ich 5 testing async-await jasmine angular-material angular
我正在尝试测试使用 Angular Material 构建的组件,但是我在Harness Loader 根据文档(“入门”部分)初始化 Material 元素时遇到了问题。我想在测试方法之外提取初始化它们的逻辑,使它们更简洁,但它似乎不起作用。
内describe():
let usernameFormField: MatFormFieldHarness;
let registrationButton: MatButtonHarness;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MaterialModule, BrowserAnimationsModule, ReactiveFormsModule],
declarations: [RegistrationComponent],
providers: [ /*provide spies */ ]
}).compileComponents().then(async () => {
fixture = TestBed.createComponent(RegistrationComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
// what works, but I don't like
/*loader.getHarness(
MatFormFieldHarness.with({selector: '#username-form-field'})
).then(harness => {
usernameFormField = harness;
});*/
// what doesn't work
usernameFormField = await loader
.getHarness(MatFormFieldHarness.with({selector: '#username-form-field'}))
// other form elements
// to my confusion, this works without any problem
registrationButton = await loader.getHarness(MatButtonHarness);
});
}));
Run Code Online (Sandbox Code Playgroud)
在await上loader.getHarness()引起了大量的错误,看似约代码“ProxyZone”没有运行。
context.js:265 Unhandled Promise rejection: Expected to be running in 'ProxyZone', but it was not found. ; Zone: <root> ; Task: Promise.then ; Value: Error: Expected to be running in 'ProxyZone', but it was not found.
at Function.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.assertPresent (zone-testing.js:210) [<root>]
at Function.setup (testbed.js:61) [<root>]
at new TestbedHarnessEnvironment (testbed.js:572) [<root>]
at TestbedHarnessEnvironment.createEnvironment (testbed.js:633) [<root>]
at TestbedHarnessEnvironment.createComponentHarness (testing.js:341) [<root>]
at TestbedHarnessEnvironment.<anonymous> (testing.js:384) [<root>]
at Generator.next (<anonymous>) [<root>]
at :9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:74:1 [<root>]
at new ZoneAwarePromise (zone-evergreen.js:960) [<root>]
at __awaiter (tslib.es6.js:70) [<root>]
at TestbedHarnessEnvironment._getQueryResultForElement (testing.js:379) [<root>]
at :9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1 [<root>]
at Array.map (<anonymous>) [<root>]
at TestbedHarnessEnvironment.<anonymous> (testing.js:366) [<root>] Error: Expected to be running in 'ProxyZone', but it was not found.
at Function.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.assertPresent (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:210:1) [<root>]
at Function.setup (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:61:1) [<root>]
at new TestbedHarnessEnvironment (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:572:1) [<root>]
at TestbedHarnessEnvironment.createEnvironment (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:633:1) [<root>]
at TestbedHarnessEnvironment.createComponentHarness (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:341:1) [<root>]
at TestbedHarnessEnvironment.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:384:1) [<root>]
at Generator.next (<anonymous>) [<root>]
at http://localhost:9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:74:1 [<root>]
at new ZoneAwarePromise (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:960:1) [<root>]
at __awaiter (http://localhost:9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:70:1) [<root>]
at TestbedHarnessEnvironment._getQueryResultForElement (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:379:25) [<root>]
at http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1 [<root>]
at Array.map (<anonymous>) [<root>]
at TestbedHarnessEnvironment.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1) [<root>]
Run Code Online (Sandbox Code Playgroud)
我还尝试使用全局async函数运行它(使用以下语法:)
context.js:265 Unhandled Promise rejection: Expected to be running in 'ProxyZone', but it was not found. ; Zone: <root> ; Task: Promise.then ; Value: Error: Expected to be running in 'ProxyZone', but it was not found.
at Function.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.assertPresent (zone-testing.js:210) [<root>]
at Function.setup (testbed.js:61) [<root>]
at new TestbedHarnessEnvironment (testbed.js:572) [<root>]
at TestbedHarnessEnvironment.createEnvironment (testbed.js:633) [<root>]
at TestbedHarnessEnvironment.createComponentHarness (testing.js:341) [<root>]
at TestbedHarnessEnvironment.<anonymous> (testing.js:384) [<root>]
at Generator.next (<anonymous>) [<root>]
at :9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:74:1 [<root>]
at new ZoneAwarePromise (zone-evergreen.js:960) [<root>]
at __awaiter (tslib.es6.js:70) [<root>]
at TestbedHarnessEnvironment._getQueryResultForElement (testing.js:379) [<root>]
at :9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1 [<root>]
at Array.map (<anonymous>) [<root>]
at TestbedHarnessEnvironment.<anonymous> (testing.js:366) [<root>] Error: Expected to be running in 'ProxyZone', but it was not found.
at Function.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.assertPresent (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:210:1) [<root>]
at Function.setup (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:61:1) [<root>]
at new TestbedHarnessEnvironment (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:572:1) [<root>]
at TestbedHarnessEnvironment.createEnvironment (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing/testbed.js:633:1) [<root>]
at TestbedHarnessEnvironment.createComponentHarness (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:341:1) [<root>]
at TestbedHarnessEnvironment.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:384:1) [<root>]
at Generator.next (<anonymous>) [<root>]
at http://localhost:9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:74:1 [<root>]
at new ZoneAwarePromise (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:960:1) [<root>]
at __awaiter (http://localhost:9876/_karma_webpack_/node_modules/tslib/tslib.es6.js:70:1) [<root>]
at TestbedHarnessEnvironment._getQueryResultForElement (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:379:25) [<root>]
at http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1 [<root>]
at Array.map (<anonymous>) [<root>]
at TestbedHarnessEnvironment.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/@angular/cdk/fesm2015/testing.js:366:1) [<root>]
Run Code Online (Sandbox Code Playgroud)
我什至尝试将这些线束提取到单独的函数中,尽可能晚地调用它们,但它也不能很好地工作:
beforeEach(async( async () => {
// magic happening here
}));
Run Code Online (Sandbox Code Playgroud)
正如这篇文章所讨论的,“双异步”结构是有效的,虽然有点笨拙。但是,它对我不起作用。唯一的变体是beforeEach(async( () => { ... } ));. 是否可以beforeEach在 async zone内部使用 async-await ,或者我是否坚持使用 Promises 手动处理所有内容?
编辑:类似的问题不仅出现在beforeEach(),而且出现在测试方法本身中,即使我没有预先初始化线束:
const usernameFormField = () => {
loader.getHarnes(...);
}
// later in code; not the most elegant, but good enough
const usernameField = await usernameFormField();
expect(await usernameField().hasErrors()).toBeFalsy();
Run Code Online (Sandbox Code Playgroud)
当我只取消注释第一个注释行时,代码会中断并且测试不会通过。当我包含异步区域时,测试通过,但错误仍然存在。我最初认为这是初始化组件的问题,但现在似乎与HarnessLoader有关。
编辑 2:Coderer 的回答链接到一些问题karma.conf.js,所以这里是我的一些配置文件:
karma.conf.js:
it('should display \'log out\' and \'my account\' buttons when user is authenticated',
async () => {
const EXAMPLE_USERNAME = 'username';
spyOnProperty(authenticationService, 'authenticatedUser')
.and.returnValue(EXAMPLE_USERNAME);
expect(fixture.componentInstance.authenticatedUser)
.toEqual(EXAMPLE_USERNAME);
const logOutButton = await loader
.getHarness(MatButtonHarness.with({text: BUTTON_LOG_OUT_TEXT}));
expect(await logOutButton.isDisabled()).toBeFalsy();
// the following line causes a problem
/*const myAccountButton = await loader
.getHarness(MatButtonHarness.with({text: BUTTON_MY_ACCOUNT_TEXT}));
expect(await myAccountButton.isDisabled()).toBeFalsy();
await myAccountButton.click();
expect(routerSpy.navigateByUrl).toHaveBeenCalled();*/
});
Run Code Online (Sandbox Code Playgroud)
src/test.ts(导入描述这里也没有工作)
// custom headless chrome from
// https://coryrylan.com/blog/building-angular-cli-projects-with-github-actions
module.exports = function (config) {
config.set({
// adding any files here didn't seem to work
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
jasmine: {
random: false
}
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/elx-front-end'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
customLaunchers: {
ChromeHeadlessCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox', '--disable-gpu']
}
}
});
};
Run Code Online (Sandbox Code Playgroud)
tsconfig.base.json:
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import "zone.js/dist/zone-testing";
import {getTestBed} from "@angular/core/testing";
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from "@angular/platform-browser-dynamic/testing";
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context("./", true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
Run Code Online (Sandbox Code Playgroud)
tsconfig.spec.json:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "es2020",
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"target": "es2018",
"strict": true,
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"paths": { /* custom paths */}
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
Run Code Online (Sandbox Code Playgroud)
片段angular.json:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
Run Code Online (Sandbox Code Playgroud)
我针对 Angular 11 提交了有关此问题的问题21632 ,因为设置如文档的入门中所述。罪魁祸首是beforeEach函数,存在三种可能的解决方案。
该async函数已被弃用并被替换为waitForAsync. 从 Angular 11(演示)开始,使用waitForAsyncinbeforeEach代替异步函数是解决该问题的一种方法。
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [MaterialModule, BrowserAnimationsModule, ReactiveFormsModule],
declarations: [RegistrationComponent]
}).compileComponents().then(async () => {
fixture = TestBed.createComponent(RegistrationComponent);
loader = TestbedHarnessEnvironment.loader(fixture);
usernameFormField = await loader
.getHarness(MatFormFieldHarness.with({selector: '#username-form-field'}))
registrationButton = await loader.getHarness(MatButtonHarness);
});
}));
Run Code Online (Sandbox Code Playgroud)
将异步函数传递给beforeEachwithoutwaitForAsync也适用于您的特定情况(演示)。但是,当不处理compileComponents承诺时,就像大多数文档那样,将调用移至TestbedHarnessEnvironment.loader函数it(demo)。
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MatButtonModule],
declarations: [ButtonHarnessExample]
}).compileComponents();
fixture = TestBed.createComponent(ButtonHarnessExample);
});
it('should click a button', async () => {
const loader = TestbedHarnessEnvironment.loader(fixture);
const button = await loader.getHarness(MatButtonHarness.with({text: 'Basic button'}));
});
Run Code Online (Sandbox Code Playgroud)
在 tsconfig.json ( demo )中将目标更改为 ES2016 。
"compilerOptions": {
"target": "es2016"
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
653 次 |
| 最近记录: |