角茉莉花测试未触发ngOnInit内部订阅

dev*_*tik 1 unit-testing rxjs typescript karma-jasmine angular6

我有一个基本的组件类,在ngOnInit内它订阅了服务调用

ngOnInit() {
    this.activityService.getActivities().subscribe(activities => {
        console.log('inside sub');
        this.recentActivities = activities;
    });
}
Run Code Online (Sandbox Code Playgroud)

因此,我包含了这个console.log,以查看此订阅是否曾经执行过。

在我的测试中,我监视此活动服务方法以返回我需要的数据的可观察集合。然后在测试中,我完成了整个fixture.detectChanges()处理,并期望我的数组长度为1。

fit('should populate recent activities', () => {
    const activities = [new ActivityBuilder()
        .withId('1').withRecentActivityActionId(RecentActivityActionType.Created).build()
    ];
    spyOn(activityService, 'getActivities').and.returnValue(of(activities));

    fixture.detectChanges();
    fixture.whenStable().then(() => {
        fixture.detectChanges();
    });
    fixture.detectChanges();

    expect(component.recentActivities.length).toBe(1);
});
Run Code Online (Sandbox Code Playgroud)

根据Angular文档,他们几乎做同样的事情,我什至尝试了fakeAsync方法,但无济于事。我在这里想念什么?为什么订阅块不执行?

dev*_*tik 5

经过数小时的fakeAsync尝试,为服务提供了模拟类,各种tick()调用,以及数十种其他帖子和稍有不同的方法,罪魁祸首归结为添加一行:component.ngOnInit();

显然,尽管fixture.detectChanges()可以肯定地调用ngOnInit,但它以某种方式保持了可观察到的冷度。当我打电话时fixture.detectChanges(),它不会进入可观察对象的订阅。一旦添加component.ngOnInit(),可观察对象就变得很热,并且订阅中的代码已执行,我可以看到控制台日志正在打印。奇怪的是,这使得随后的fixture.detectChanges()调用也跳入每个后续调用的订阅代码中。

这是我的规格文件的简化版本,希望这对以后遇到相同问题的人有所帮助。fakeAsync和sync区域仍然通过了测试,我以为我需要在fakeAsync区域内至少需要一个tick(),但这不是必需的。

describe('RecentActivityComponent', () => {
let component: RecentActivityComponent;
let fixture: ComponentFixture<RecentActivityComponent>;
let activityService: ActivityService;

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports: [AccordionModule, FontAwesomeModule, HttpClientTestingModule],
        declarations: [ RecentActivityComponent ],
        providers: [AccordionConfig, ActivityService]
    }).compileComponents();
}));

beforeEach(async () => {
    fixture = TestBed.createComponent(RecentActivityComponent);
    component = fixture.componentInstance;
    activityService = TestBed.get(ActivityService);
});

it('should populate recent activities', fakeAsync( () => {
    const activities = [new ActivityBuilder()
        .withId('1').withRecentActivityActionId(RecentActivityActionType.Created).build()
    ];
    spyOn(activityService, 'getActivities').and.returnValue(of(activities));
    component.ngOnInit();
    expect(component.recentActivities.length).toBe(1);
}));

it('should populate recent activities', () => {
    const activities = [new ActivityBuilder()
        .withId('1').withRecentActivityActionId(RecentActivityActionType.Created).build()
    ];
    spyOn(activityService, 'getActivities').and.returnValue(of(activities));
    component.ngOnInit();
    expect(component.recentActivities.length).toBe(1);
});
Run Code Online (Sandbox Code Playgroud)

});