Angular 2 测试组件给出“错误:未捕获(承诺):错误:模板解析错误”
Posted
技术标签:
【中文标题】Angular 2 测试组件给出“错误:未捕获(承诺):错误:模板解析错误”【英文标题】:Angular 2 Testing Component Gives "Error: Uncaught (in promise): Error: Template parse errors" 【发布时间】:2017-02-17 14:21:12 【问题描述】:我最近制作了一个包含多个组件和服务的 ng2(使用 2.0.1)应用程序。我正在测试(Karma Jasmine)我的 HeaderComponent ,其中包含我的 UserService (它使用扩展的 Http 类)。
我已经从Angular.io Docs 复制了简单的测试来监视服务并等待组件初始化后检查服务功能是否已被触发及其内容。 每次我使用 fakeAsync(和 async)运行最后一个测试时,它会检查 header.component 中 currentUser 变量的内容,我收到以下错误...
Error: Uncaught (in promise): Error: Template parse errors:
'header-section' is not a known element:
1. If 'header-section' is an Angular component, then verify that it is part of this module.
2. If 'header-section' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
[ERROR ->]<header-section></header-section>
<router-outlet></router-outlet>
<footer-section></footer-sectio"): AppComponent@1:2
'router-outlet' is not a known element:
1. If 'router-outlet' is an Angular component, then verify that it is part of this module.
2. If 'router-outlet' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
<header-section></header-section>
[ERROR ->]<router-outlet></router-outlet>
<footer-section></footer-section>"): AppComponent@2:2
'footer-section' is not a known element:
1. If 'footer-section' is an Angular component, then verify that it is part of this module.
2. If 'footer-section' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
<header-section></header-section>
<router-outlet></router-outlet>
[ERROR ->]<footer-section></footer-section>"): AppComponent@3:2
这些选择器来自我的 AppComponent...
import Component, OnInit from '@angular/core';
@Component(
selector: 'my-app',
moduleId: module.id,
template: `
<header-section></header-section>
<router-outlet></router-outlet>
<footer-section></footer-section>`
)
export class AppComponent
constructor()
test(): string
return 'this is a test';
我的header.component.spec...
import Http, Request, RequestOptionsArgs, Response, XHRBackend, RequestOptions, ConnectionBackend, Headers from '@angular/http';
import HttpIntercept from '../../services/auth/auth.service';
import BrowserModule from '@angular/platform-browser';
import HttpModule, JsonpModule from '@angular/http';
import FormsModule from '@angular/forms';
import RouterTestingModule from "@angular/router/testing";
import appRoutes from '../../routes';
import Cookie from 'ng2-cookies/ng2-cookies';
import AppComponent from '../app/app.component';
import HeaderComponent from './header.component';
import FooterComponent from '../footer/footer.component';
import HomeComponent from '../home/home.component';
import Four0FourComponent from '../404/four0four.component';
import UserProfileComponent from '../user-profile/user-profile.component';
import UserService from '../../services/user/user.service';
import ClockService from '../../services/clock/clock.service';
import Observable from 'rxjs/Observable';
import TestBed, async, fakeAsync, tick from '@angular/core/testing';
import By from '@angular/platform-browser';
import User from '../../models/user/user.model';
class MockRouter public navigate() ;
describe('HeaderComponent Test', () =>
let fixture;
let comp;
let userService;
let spy;
let user = new User(
_id: 123456,
userName: 'testName',
firstName: 'testFirst',
lastName: 'testLast',
email: 'test@email.com',
create: 'now',
role: 'user'
);
beforeEach(() =>
TestBed.configureTestingModule(
imports: [
BrowserModule,
HttpModule,
FormsModule,
JsonpModule,
RouterTestingModule.withRoutes(appRoutes)
],
declarations: [
HomeComponent,
UserProfileComponent,
Four0FourComponent,
FooterComponent,
HeaderComponent,
AppComponent
],
providers: [
provide: Http,
useFactory: (
backend: XHRBackend,
defaultOptions: RequestOptions) =>
new HttpIntercept(backend, defaultOptions),
deps: [XHRBackend, RequestOptions]
,
Cookie
]
);
fixture = TestBed.createComponent(HeaderComponent);
comp = fixture.componentInstance;
userService = fixture.debugElement.injector.get(UserService);
spy = spyOn(userService, 'getMe')
.and.returnValue(Observable.of(user));
);
it('should instantiate component', () =>
expect(fixture.componentInstance instanceof HeaderComponent).toBe(true);
);
it('should not show currentUser before OnInit', () =>
expect(spy.calls.any()).toBe(false, 'getMe not yet called');
);
it('should still not show currentUser after component initialized', () =>
// Set cookie token, for the getMe to call
Cookie.set('token', 'test_token_alpha');
fixture.detectChanges();
expect(spy.calls.any()).toBe(true, 'getMe called');
);
//The problem test is bellow
it('should show currentUser after getMe promise', fakeAsync(() =>
fixture.detectChanges();
tick();
fixture.detectChanges();
expect(comp.currentUser).toEqual(user);
));
);
这是我的 header.component...
import Component from '@angular/core';
import Cookie from 'ng2-cookies/ng2-cookies';
import Observable from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import UserService from '../../services/user/user.service';
import ClockService from '../../services/clock/clock.service';
import User from '../../models/user/user.model';
@Component(
selector: 'header-section',
providers: [
UserService,
ClockService
],
moduleId: module.id,
template: `
<style>
header
background: rgb(55, 129, 215);
position: relative;
.user-sign
position: absolute;
top:0;
right:0;
margin: 23px 5%;
.app-title
font-family: cursive;
padding: 15px;
text-align: center;
font-size: 36px;
color: white;
.user-sign button:hover
cursor: pointer;
.active
color: orange;
</style>
<header>
<a routerLink='/' routerLinkActive='active'>Home</a>
<a routerLink='/profile' routerLinkActive='active'>Profile</a>
<a routerLink='/yoloswaq69420blazeitfgt' routerLinkActive='active'>404</a>
<div class='user-sign'>
<h3 *ngIf='currentUser'>Welcome, currentUser.userName</h3>
<button *ngIf='!currentUser' type='button' (click)='testRegisterUser()'>Sign up</button>
<button *ngIf='!currentUser' type='button' (click)='testUser()'>Sign in</button>
<button type='button' (click)='logout()'>Sign out</button>
</div>
<h1 class='app-title'>MEA2N Fullstack</h1>
</header>`
)
export class HeaderComponent
errorMessage: string;
public currentUser: User;
clock = this.clockService.currentTime;
constructor(private userService: UserService, private clockService: ClockService)
ngOnInit()
let token = Cookie.get('token');
if (token)
this.userService.getMe().subscribe(user => this.currentUser = user);
login(email: string, password: string)
this.userService.login(email, password)
.subscribe(() =>
return this.userService.getMe()
.subscribe(user =>
this.currentUser = user;
)
);
logout()
this.userService.logout();
this.currentUser = null;
registerUser(username: string, email: string, password: string)
this.userService.signup(username, email, password)
.subscribe(() =>
return this.userService.getMe()
.subscribe(user =>
this.currentUser = user;
)
);
testUser()
this.login('jc.thomas4214@gmail.com', 'flight1855');
testRegisterUser()
this.registerUser('Jason', 'jc.thomas4214@gmail.com', 'flight1855');
我怀疑发生此错误是因为我初始化 TestBed.configureTestingModule() 的方式。
我试过了……
-
重新排序 app.module 和 TestBed 模块声明
向两个模块添加架构:[CUSTOM_ELEMENTS_SCHEMA]
【问题讨论】:
Angular 2 Karma Test 'component-name' is not a known element的可能重复 【参考方案1】:由于本例是对 Header 组件进行单元测试,所以不需要包含其他模块和组件
TestBed 可以如下所示:
beforeEach(() =>
TestBed.configureTestingModule(
imports: [
AppModule
],
providers: [
provide: UserService, useClass: MockUserService,
provide: ClockService, useClass: MockClockService
]
);
fixture = TestBed.createComponent(HeaderComponent);
);
在此示例中,服务已被模拟,但也可以像您为 UserService 所做的那样被监视
【讨论】:
非常感谢您的回复!我尝试了你的建议,但它给出了一个不同的错误。错误:client/app/components/header/header.component.js 类 HeaderComponent 中的错误 - 内联模板:27:4 原因:未设置基本 href。请为 APP_BASE_HREF 令牌提供值或向文档添加基本元素。错误:未设置基本 href。请提供 APP_BASE_HREF 令牌的值或向文档添加基本元素。 所以我将 provide: APP_BASE_HREF, useValue: '/' 添加到提供程序列表中,现在我得到这个:错误:客户端/应用程序/组件/标题/标题.组件中的错误。 js 类 HeaderComponent - 内联模板:27:4 原因:在注入路由器之前引导至少一个组件 抱歉,不看代码就帮不上忙。你的 AppModule 是什么样的?你能创建一个 plunker 吗? 这是file 的链接。感谢所有帮助,非常感谢 :) AppModule 与我原来的帖子的 TestBed 模块基本相同,但路由除外以上是关于Angular 2 测试组件给出“错误:未捕获(承诺):错误:模板解析错误”的主要内容,如果未能解决你的问题,请参考以下文章
带有 ControlValueAccessor 测试的 Angular 2(4) 组件
为使用 Observables 的 Angular 2 组件编写 Jasmine 测试
使用 Jasmine 间谍进行 Angular 2 组件测试“没有 Http 提供者!”错误
如何测试 angular 2 组件,其中嵌套组件具有自己的依赖项? (TestBed.configureTestingModule)