Jasmine测试中的模板解析错误,但不是实际的应用程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jasmine测试中的模板解析错误,但不是实际的应用程序相关的知识,希望对你有一定的参考价值。

我开发了一个茉莉花规格测试角度2组分MiddleRowComponent。当我运行jasmine测试时,它会给出以下错误:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:

但是,如果我像往常一样在浏览器中运行我的Web应用程序,则不会发生错误。 circles确实是该模块的一部分。 custom-button是导入的共享模块的一部分。这是module.ts:

    import { NgModule }           from '@angular/core';
import { CommonModule }       from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import * as LandingPage from './index';

@NgModule({
   imports: [ CommonModule, SharedModule ],
   declarations: [
      LandingPage.MiddleRowComponent,
      LandingPage.LandingPageComponent,
      LandingPage.CirclesComponent
   ],
   exports: [ LandingPage.LandingPageComponent ],
})
export class LandingPageModule { }

一切都是导入并声明应该是,并且在运行应用程序时无需测试。鉴于从单独的模板文件中获取组件模板的异构性,我使用done来进行beforeEach工作。我用jasmine spec runner html文件测试了。为什么MiddleRowComponent使用的组件不是茉莉花测试中的已知元素,而是在正常运行应用程序时?

这是茉莉花规格:

import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { MiddleRowComponent } from './middle-row.component';

let comp: MiddleRowComponent;
let fixture: ComponentFixture<MiddleRowComponent>;
let de: DebugElement;
let el: HTMLElement;

describe('MiddleRowComponent', () => {
   var fixture: any;
   var comp: any;
    beforeAll(() => {
        TestBed.resetTestEnvironment();
        TestBed.initTestEnvironment(BrowserDynamicTestingModule,
            platformBrowserDynamicTesting());
    });

    beforeEach((done) => {
        TestBed.configureTestingModule({
            declarations: [MiddleRowComponent], // declare the test component
        }).compileComponents().then(() => {
            fixture = TestBed.createComponent(MiddleRowComponent);
            comp = fixture.componentInstance; // MiddleRowComponent test instance
            // query for the title <h1> by CSS element selector
            de = fixture.debugElement.query(By.css('h1'));
            el = de.nativeElement;
            done();
        });
    });

    it('should display original title', () => {
        fixture.detectChanges();
        expect(el.textContent).toContain(comp.word);
    });

    it('should display a different test title', () => {
        comp.word = 'Test Title';
        fixture.detectChanges();
        expect(el.textContent).toContain('Test Title');
    });
});

完整错误:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9 ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9
    at TemplateParser.parse (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:7730:21)
    at RuntimeCompiler._compileTemplate (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17573:53)
    at eval (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:64)
    at Set.forEach (native)
    at RuntimeCompiler._compileComponents (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:21)
    at createResult (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17404:21)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:232:26)
    at ProxyZoneSpec.onInvoke (http://localhost:3002/node_modules/zone.js/dist/proxy.js:79:39)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:231:32)
    at Zone.run (http://localhost:3002/node_modules/zone.js/dist/zone.js:114:43)consoleError @ zone.js:388_loop_1 @ zone.js:417drainMicroTaskQueue @ zone.js:421ZoneTask.invoke @ zone.js:339
zone.js:390 Error: Uncaught (in promise): Error: Template parse errors:(…)
答案

那么,你的测试模块只声明了MiddleRowComponent。所以它不了解CircleComponent:

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent], // declare the test component
})

在测试模块的声明中添加所有必需的组件,或将LandingPageModule添加到测试模块的导入中。

另一答案

我遇到了类似的问题并找到了这个页面,虽然JB Nizet的回答为我找到了一个解决方案,但它对我来说并不适用。我并没有试图从他对原始问题的坚定答案中解脱出来,只是试图帮助下一个出现的人。

我的问题与OP完全一样,只是我的自定义组件(本例中为MiddleRowComponent)使用了第三方组件。给出了关于我的模板中使用的第三方标记的单元测试错误,即使它在实际应用中运行得很好。我的解决方案是在我的测试模块中为第三方提供imports

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent],
    imports: [TheThirdPartyModule]
})

然后我的单元测试运行没有错误。希望有所帮助!

另一答案

另一种选择是将NO_ERRORS_SCHEMA模式添加到测试设置中。任何无法识别的组件现在都不会导致错误。在使用Angular Material Design等第三方模块时,我经常使用它。

import { NO_ERRORS_SCHEMA } from '@angular/core';
...
  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [MiddleRowComponent],
        schemas: [NO_ERRORS_SCHEMA]
      }).compileComponents();
    })
  );

以上是关于Jasmine测试中的模板解析错误,但不是实际的应用程序的主要内容,如果未能解决你的问题,请参考以下文章

使用 Karma Jasmine 的 Angular 1.5 组件模板单元测试

ng 测试模板解析错误“ngb-carousel”不是已知元素

Angular Jasmine单元测试。类型错误:this.sitesTable.renderRows不是一个函数。

afterAll ReferenceError 中抛出错误:未定义模块,nodejs 中的 Karma/Jasmine 测试错误

在 Jasmine 中访问 Meteor 模板辅助函数以进行集成测试

单元测试 typescript 指令模板 karma-jasmine,html 未定义