Unit testing angular2测试,如何模拟子组件

Unit testing angular2测试,如何模拟子组件,unit-testing,testing,jasmine,angular,components,Unit Testing,Testing,Jasmine,Angular,Components,如何在jasmine测试中模拟子组件 我有MyComponent,它使用MyNavbarComponent和MyToolbarComponent 从'angular2/core'导入{Component}; 从“./my navbar.component”导入{MyNavbarComponent}; 从“./mytoolbar.component”导入{MyToolbarComponent}; @组成部分({ 选择器:“我的应用程序”, 模板:` {{foo}} `, 指令:[MyNavbarC

如何在jasmine测试中模拟子组件

我有
MyComponent
,它使用
MyNavbarComponent
MyToolbarComponent

从'angular2/core'导入{Component};
从“./my navbar.component”导入{MyNavbarComponent};
从“./mytoolbar.component”导入{MyToolbarComponent};
@组成部分({
选择器:“我的应用程序”,
模板:`
{{foo}}
`,
指令:[MyNavbarComponent,MyToolbarComponent]
})
导出类MyComponent{}
当我测试这个组件时,我不想加载和测试这两个子组件;MyNavbarComponent,MyToolbarComponent,所以我想模拟它

我知道如何使用
provide(MyService,useClass(…)
模拟服务,但我不知道如何模拟指令;组成部分

beforeach(()=>{
setBaseTestProviders(
测试浏览器平台提供商,
测试\浏览器\应用程序\提供者
);
//TODO:要对此组件测试模拟不必要的指令吗
//哪些是MyNavbarComponent和MyToolbarComponent
})
它('应该绑定到{foo}}',injectAsync([TestComponentBuilder],(tcb)=>{
返回tcb.createAsync(MyComponent)。然后((fixture)=>{
让DOM=fixture.nativeElement;
设myComponent=fixture.componentInstance;
myComponent.foo='foo';
fixture.detectChanges();
expect(DOM.innerHTML).toMatch('FOO');
});
});
这是我的plunker示例


多亏了埃里克·马丁内斯,我找到了这个解决方案

我们可以使用
overrideDirective
函数,这里有文档记录,

它需要三个prarmeters; 1.要实施的组件 2.要覆盖的子组件 3.模拟组件

解决方案在这里

这是plunker中的代码示例

从“../src/my navbar.component”导入{MyNavbarComponent};
从“../src/my toolbar.component”导入{MyToolbarComponent};
@组件({模板:'})
类EmptyComponent{}
描述('MyComponent',()=>{
beforeach(injectAsync([TestComponentBuilder],(tcb)=>{
返回tcb
.overrideDirective(MyComponent、MyNavbarComponent、EmptyComponent)
.overrideDirective(MyComponent、MyToolbar组件、EmptyComponent)
.createAsync(MyComponent)
.然后((componentFixture:componentFixture)=>{
this.fixture=组件fixture;
});
));
它('应该绑定到{{foo}}',()=>{
设el=this.fixture.nativeElement;
让myComponent=this.fixture.componentInstance;
myComponent.foo='foo';
fixture.detectChanges();
expect(el.innerHTML).toMatch('FOO');
});
});

如果在
TestBed
中使用
模式:[CUSTOM\u ELEMENTS\u SCHEMA]
,则被测组件将不会加载子组件

从'@angular/core'导入{CUSTOM_ELEMENTS_SCHEMA};
从“@angular/core/testing”导入{TestBed,async};
从“/my.component”导入{MyComponent};
描述('App',()=>{
在每个之前(()=>{
试验台
.配置测试模块({
声明:[
真菌成分
],
模式:[自定义元素\u模式]
});
});
它(`should have as title'app works!'`,异步(()=>{
让fixture=TestBed.createComponent(MyComponent);
设app=fixture.debugElement.componentInstance;
expect(app.title).toEqual(“待办事项列表”);
}));
});
这在Angular 2.0的发布版本中起作用。


自定义元素模式
的另一个替代方案是
无错误模式

根据要求,我发布了另一个关于如何使用
输入
/
输出
模拟子组件的答案:

因此,让我们先说我们有
TaskListComponent
,它显示任务,并在单击其中一个任务时刷新:


应用程序任务
是一个子组件,具有
[task]
输入和
(单击)
输出

很好,现在我们想为我的
TaskListComponent
编写测试,当然我们不想测试真正的
apptask
组件

因此,正如@Klas所建议的,我们可以使用以下配置我们的
TestModule

SCHEMA:[自定义元素\u SCHEMA]
我们可能在构建或运行时都不会得到任何错误,但是除了子组件的存在之外,我们将无法测试更多的错误

那么我们如何模拟子组件呢?

首先,我们将为我们的子组件(相同的选择器)定义一个模拟指令:

@指令({
选择器:“应用程序任务”
})
类mocktask指令{
@输入('任务')
公共任务:ITask;
@输出('单击')
public clickEmitter=new EventEmitter();
}
现在我们将在测试模块中声明它:

let夹具:组件夹具;
让cmp:TaskListComponent;
在每个之前(()=>{
TestBed.configureTestingModule({
声明:[TaskListComponent,**MockTaskDirective**],
//模式:[自定义元素\u模式],
供应商:[
{
提供:任务服务,
useClass:MockService
}
]
});
fixture=TestBed.createComponent(TaskListComponent);
**fixture.autoDetectChanges()**
cmp=夹具。组件状态;
});
  • 请注意,由于夹具子组件的生成是在其创建后异步进行的,因此我们激活了其autoDetectChanges功能
在我们的测试中,我们现在可以查询指令,访问其DebugElement的注入器,并通过它获取模拟指令实例:

从'@angular/platform browser'导入{By};
const mockTaskEl=fixture.debugElement.query(By.directive(MockTaskDirective));
const mockTaskCmp=mockTaskEl.injector.get(MockTaskDirective)作为MockTaskDirective;
[此部分通常应位于每个之前的
部分中,以获取更清晰的代码。]

从这里开始,测试就是小菜一碟:)

it('应包含任务组件
import { TestBed } from '@angular/core/testing';
import { MyComponent } from './src/my.component';
import { MockComponent } from 'ng2-mock-component';

describe('MyComponent', () => {

  beforeEach(() => {

    TestBed.configureTestingModule({
      declarations: [
        MyComponent,
        MockComponent({ 
          selector: 'my-subcomponent', 
          inputs: ['someInput'], 
          outputs: [ 'someOutput' ]
        })
      ]
    });

    let fixture = TestBed.createComponent(MyComponent);
    ...
  });

  ...
});