Unit testing Angular2单元测试:测试组件';s构造函数

Unit testing Angular2单元测试:测试组件';s构造函数,unit-testing,angular,angular2-testing,Unit Testing,Angular,Angular2 Testing,所有内容都在标题中:如何测试组件的构造函数中完成了什么? 仅供参考,我正在使用一个需要设置的服务,我想看看我在构造函数中调用的两个方法是否被正确调用 我的组件的构造函数: constructor( public router: Router, private profilService: ProfileService, private dragula: DragulaService, private alerter: AlertService ) { dragula.drag

所有内容都在标题中:如何测试组件的构造函数中完成了什么?

仅供参考,我正在使用一个需要设置的服务,我想看看我在构造函数中调用的两个方法是否被正确调用

我的组件的构造函数:

constructor(
  public router: Router,
  private profilService: ProfileService,
  private dragula: DragulaService,
  private alerter: AlertService
) {
  dragula.drag.subscribe((value) => {
    this.onDrag(value);
  });
  dragula.dragend.subscribe((value) => {
    this.onDragend(value);
  });
}

我会使用DI系统注入一个假服务,这意味着要编写如下测试:

description('您的组件',()=>{
let夹具:组件夹具;
让虚假服务;
设dragSubject=新的ReplaySubject(1);
...
beforeach(异步(()=>{
fakeService={
drag:dragSubject.asObservable(),
... 
};
TestBed.configureTestingModule({
声明:[您的组件,…],
供应商:[
{provide:dragularservice,useValue:fakeService},
...
],
});
}));
在每个之前(()=>{
fixture=TestBed.createComponent(您的组件);
fixture.detectChanges();
});
它('在发生拖动事件时应该做些什么',()=>{
dragSubject.next({…});
fixture.detectChanges();
...
});
});
这允许您随时通过调用主题上的
.next
触发“拖动事件”,这会导致调用假服务上字段的订阅者。然后,你可以对你期望的结果做出断言

请注意,您不需要自己调用
构造函数
;当DI系统实例化组件时,即调用
TestBed.createComponent
时,调用此方法


我建议您不要监视组件方法(例如,
this.onDrag
),只需确保它们被调用,而是测试这些方法在结果发生时应该做什么;这使得测试对特定实现中的更改更加健壮(我在我的博客上写了一些关于这方面的内容:)。

测试构造函数中任何内容的简单方法是创建组件实例,然后测试它

it('should call initializer function in constructor', () => {
  TestBed.createComponent(HomeComponent); // this is the trigger of constructor method
 expect(sideNavService.initialize).toHaveBeenCalled(); // sample jasmine spy based test case
});
需要注意的一点是,如果您想区分构造函数和ngOnInit,那么就不要调用
fixture.detectChanges()
inside
beforeach()
。无论何时需要,都可以手动调用。

因为OP声明“我想看看我在构造函数中调用的两个方法是否正确调用。”我有一个更好的方法

编写一个单元测试。你不需要使用试验台来做这件事。这会大大降低你的考试速度。手动实例化模拟。在您感兴趣的方法上设置spies,然后使用您实例化并设置spies的存根手动调用组件构造函数。然后测试spied方法是否被正确调用


关键是从原始服务类扩展存根
jasmine.createSpyObj
有助于模拟角度类,如
Router

使用测试台注入一个假的
DragularService
,并监视其方法?我想,问题是我无法联系到Contractor来测试我的存根是否被调用。你说“联系到构造函数”是什么意思?当DI系统在测试床中实例化组件时,当您
TestBed.createComponent(YourComponent)
时,会调用它。我的意思是,我想测试构造函数中编写的代码是否被触发,通过像测试任何其他方法一样测试构造函数,您可以通过手动创建
新组件(…)
来调用构造函数,但是您应该让DI系统完成它的工作。这就是单元在实践中的使用方式,考虑一下其他组件看到的公共接口。如下所示,听起来您正在编写(或试图编写)与当前实现联系太紧密的脆弱测试。因此,您告诉我,与其测试构造函数,不如调用所需的方法,看看它们是否被调用?(我是单元测试新手,我认为你必须测试每个方法,包括构造函数)@trichetriche不,我是说你通过确保服务上的事件连接到正确的行为来测试构造函数做了什么。您可以简单地测试构造函数是否在假服务上的适当监视字段上调用
.subscribe
(例如执行类似
{drag:jasmine.createSpyObj('fake drag event',['subscribe']),…}
)的操作,但这与当前特定的实现密切相关,而不是与您正在实现的实际功能密切相关。@Trichetrich该服务不是在构造函数中调用的,只是订阅的。您试图实现的实际行为,以及您应该测试的,是发生拖动事件时发生的任何情况。这就是上面的测试检查的内容。“我的意思是我不应该叫它”-叫什么?“因此,如果有人更改构造函数代码,它会抛出一个错误”-如果构造函数更改,导致服务不再订阅,并且没有任何其他更改以确保功能仍然有效,那么测试将失败。“这就是应该发生的事情。”特里谢:没问题。事实上,我最近为一些同事写了一篇关于角度测试的博客,你可能会发现它很有用:非常感谢你的回答!已经有了一个公认的答案,它特别适合我。你的方法并不是这样,因为这是一个关于每个组件的问题,我做过的每个服务都有一些代码进入构造函数,你可以对每个组件都这样做。您真的不能将测试台用于纯单元测试。否则,您的测试需要很长时间才能完成。相信我,我现在正在努力解决这个问题。请注意:无意冒犯,但在提供这么多功能的同时避免使用可用的抽象是有点愚蠢的。例如,当我测试我的服务时,模拟后端非常有用!这需要一个试验台。在200多个测试的14k行代码中,我的测试时间是6秒