我如何在茉莉花测试中模拟子组件?
我有MyComponent,它使用MyNavbarComponent和MyToolbarComponent
import {Component} from 'angular2/core'; import {MyNavbarComponent} from './my-navbar.component'; import {MyToolbarComponent} from './my-toolbar.component'; @Component({ selector: 'my-app',template: ` <my-toolbar></my-toolbar> {{foo}} <my-navbar></my-navbar> `,directives: [MyNavbarComponent,MyToolbarComponent] }) export class MyComponent {}
当我测试这个组件时,我不想加载和测试这两个子组件; MyNavbarComponent,MyToolbarComponent,所以我想嘲笑它。
我知道如何使用提供(MyService,useClass(…))来嘲笑服务,但我不知道如何模拟指令;组件;
beforeEach(() => { setBaseTestProviders( TEST_BROWSER_PLATFORM_PROVIDERS,TEST_BROWSER_APPLICATION_PROVIDERS ); //TODO: want to mock unnecessary directives for this component test // which are MyNavbarComponent and MyToolbarComponent }) it('should bind to {{foo}}',injectAsync([TestComponentBuilder],(tcb) => { return tcb.createAsync(MyComponent).then((fixture) => { let DOM = fixture.nativeElement; let myComponent = fixture.componentInstance; myComponent.foo = 'FOO'; fixture.detectChanges(); expect(DOM.innerHTML).toMatch('FOO'); }); });
这是我的榜样
根据要求,我发布了关于如何通过输入/输出模拟子组件的另一个答案:
原文链接:https://www.f2er.com/angularjs/144193.html所以让我们开始说我们有TaskListComponent显示任务,并且当其中一个被点击时刷新:
<div id="task-list"> <div *ngFor="let task of (tasks$ | async)"> <app-task [task]="task" (click)="refresh()"></app-task> </div> </div>
应用任务是具有[任务]输入和(点击)输出的子组件。
好的,现在我们要为我的TaskListComponent编写测试,当然我们不想测试真正的app-task组件。
所以@Klas建议我们可以配置我们的TestModule:
schemas: [CUSTOM_ELEMENTS_SCHEMA]
我们可能不会在构建或运行时收到任何错误,但是除了子组件的存在之外,我们将无法进行测试。
那么我们如何模拟子组件呢?
首先我们为我们的子组件定义一个mock指令(同一个选择器):
@Directive({ selector: 'app-task' }) class MockTaskDirective { @Input('task') public task: ITask; @Output('click') public clickEmitter = new EventEmitter<void>(); }
现在我们将在测试模块中声明它:
let fixture : ComponentFixture<TaskListComponent>; let cmp : TaskListComponent; beforeEach(() => { TestBed.configureTestingModule({ declarations: [TaskListComponent,**MockTaskDirective**],// schemas: [CUSTOM_ELEMENTS_SCHEMA],providers: [ { provide: TasksService,useClass: MockService } ] }); fixture = TestBed.createComponent(TaskListComponent); **fixture.autoDetectChanges();** cmp = fixture.componentInstance; });
>请注意,由于灯具的子组件的生成在其创建后异步发生,因此我们激活其autoDetectChanges功能。
在我们的测试中,我们现在可以查询指令,访问其DebugElement的注入器,并通过它获取我们的模拟指令实例:
import { By } from '@angular/platform-browser'; const mockTaskEl = fixture.debugElement.query(By.directive(MockTaskDirective)); const mockTaskCmp = mockTaskEl.injector.get(MockTaskDirective) as MockTaskDirective;
[这部分通常在前面的部分,更清洁的代码。]
从这里,测试是一块蛋糕:)
it('should contain task component',()=> { // Arrange const mockTaskEl = fixture.debugElement.query(By.directive(MockTaskDirective)); // Assert expect(mockTaskEl).toBeTruthy(); }); it('should pass down task object',()=>{ // Arrange const mockTaskEl = fixture.debugElement.query(By.directive(MockTaskDirective)); const mockTaskCmp = mockTaskEl.injector.get(MockTaskDirective) as MockTaskDirective; // Assert expect(mockTaskCmp.task).toBeTruthy(); expect(mockTaskCmp.task.name).toBe('1'); }); it('should refresh when task is clicked',()=> { // Arrange spyOn(cmp,'refresh'); const mockTaskEl = fixture.debugElement.query(By.directive(MockTaskDirective)); const mockTaskCmp = mockTaskEl.injector.get(MockTaskDirective) as MockTaskDirective; // Act mockTaskCmp.clickEmitter.emit(); // Assert expect(cmp.refresh).toHaveBeenCalled(); });