Angular单元测试初始化失败:TypeError订阅问题求助
问题解决
错误原因:测试中给FluxStore提供的是空对象{},但组件ngOnInit里会调用this.store.Accounts.subscribe(),此时store.Accounts为undefined,导致抛出读取subscribe的错误。同时组件依赖的@ViewChild子组件未在测试环境中处理,也会引发潜在报错,需一并修正。
修正后的测试文件代码
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { AccountComponent } from "./account.component"; import { FluxStore } from 'src/app/shared/services/flux-store'; import { fluxDispatcherToken } from 'src/app/shared/helpers/flux.configuration'; import { FluxAction, FluxActionTypes } from 'src/app/shared/types/actions.type'; import { Subject } from 'rxjs'; // 模拟子组件,避免ViewChild引用报错 class MockManualTransactionFormComponent { manualtransactionform = { nativeElement: { classList: { add: () => {} } } }; } class MockCsvTransactionFormComponent { modal = { nativeElement: { classList: { add: () => {} } } }; } describe("AccountComponent", () => { let component: AccountComponent; let fixture: ComponentFixture<AccountComponent>; let mockStore: jasmine.SpyObj<FluxStore>; let mockDispatcher: Subject<FluxAction>; let mockAccountsSubject: Subject<any[]>; beforeEach(async () => { // 创建模拟的Accounts Subject,供组件订阅 mockAccountsSubject = new Subject<any[]>(); // 创建FluxStore的Spy对象,模拟Accounts属性 mockStore = jasmine.createSpyObj('FluxStore', [], { Accounts: mockAccountsSubject }); mockDispatcher = new Subject<FluxAction>(); await TestBed.configureTestingModule({ declarations: [ AccountComponent, MockManualTransactionFormComponent, MockCsvTransactionFormComponent ], schemas: [CUSTOM_ELEMENTS_SCHEMA], providers: [ { provide: FluxStore, useValue: mockStore }, { provide: fluxDispatcherToken, useValue: mockDispatcher }, ], imports: [] }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(AccountComponent); component = fixture.componentInstance; // 手动赋值ViewChild引用,避免undefined component.manualTransactionModal = new MockManualTransactionFormComponent(); component.csvTransactionModal = new MockCsvTransactionFormComponent(); fixture.detectChanges(); }); it('should create component successfully', () => { expect(component).toBeTruthy(); }); it('should update accounts and data status when receiving non-empty data', () => { const testAccounts = [{ id: 1, name: 'Test Savings Account' }]; mockAccountsSubject.next(testAccounts); expect(component.accounts).toEqual(testAccounts); expect(component.data).toBe('data'); }); it('should set empty accounts and nodata status when receiving empty array', () => { mockAccountsSubject.next([]); expect(component.accounts).toEqual([]); expect(component.data).toBe('nodata'); }); it('should set isloading status when receiving data without length property', () => { mockAccountsSubject.next({} as any); expect(component.data).toBe('isloading'); }); afterEach(() => { // 清理Subject,避免测试间内存泄漏 mockAccountsSubject.complete(); mockDispatcher.complete(); }); })
关键修正点
- 模拟FluxStore:用
jasmine.createSpyObj创建包含AccountsSubject的模拟对象,确保组件能正常调用subscribe方法。 - 处理子组件依赖:创建模拟子组件类并手动赋值给组件的
@ViewChild属性,避免调用弹窗方法时出现undefined错误。 - 覆盖业务场景:添加测试用例验证组件对有数据、空数据、加载状态的不同处理逻辑。
- 资源清理:在
afterEach中完成Subject,避免测试间的内存泄漏问题。
内容的提问来源于stack exchange,提问作者kayssmile
相关产品推荐
相关产品推荐

