Angular测试:如何获取Service中BehaviorSubject属性的默认值?
解决方法
你遇到的问题是因为jasmine.createSpyObj只会初始化你明确指定的方法,不会自动创建类里的属性(比如props),所以直接访问testServiceSpy.props会得到undefined。下面给两种可行的解决方式:
方式一:创建SpyObj时初始化属性
jasmine.createSpyObj支持第三个参数,用来定义要初始化的属性及对应值。你可以在这里传入带有默认BehaviorSubject的props:
beforeEach(async(() => { // 初始化带有props属性的spy对象 testServiceSpy = jasmine.createSpyObj<TestService>("TestService", ["test"], // 要spy的方法列表 { props: new BehaviorSubject<boolean>(false), // 初始化props属性 props$: new BehaviorSubject<boolean>(false).asObservable() // 复用同一实例更严谨:可以改成props.asObservable() } ); // 注意:你原来的代码里useValue写错了变量名,要改成testServiceSpy TestBed.configureTestingModule({ declarations: [ MainComponent ], schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], imports:[HttpClientTestingModule], providers:[ { provide: TestService, useValue: testServiceSpy, // 修正变量名错误 }, ] }).compileComponents(); }));
之后你就能通过testServiceSpy.props.value获取到默认的false了。
方式二:实例化真实服务,仅Spy特定方法
如果你的测试需要保留服务的大部分真实逻辑(比如props与props$的关联关系),只需要拦截test方法,可以直接实例化真实的TestService,再单独Spytest方法:
beforeEach(async(() => { const realTestService = new TestService(); // 只spy test方法,保留其他属性的真实逻辑 testServiceSpy = jasmine.createSpyObj<TestService>("TestService", ["test"]); // 把真实服务的属性赋值给spy对象 testServiceSpy.props = realTestService.props; testServiceSpy.props$ = realTestService.props$; TestBed.configureTestingModule({ declarations: [ MainComponent ], schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA], imports:[HttpClientTestingModule], providers:[ { provide: TestService, useValue: testServiceSpy, }, ] }).compileComponents(); }));
这种方式更贴近真实的服务行为,适合需要测试组件对props$订阅逻辑的场景。
另外提醒下你原来代码里的小错误:useValue里写的technicalFacilitiesServiceSpy是不存在的变量,应该改成testServiceSpy,否则会导致测试报错。
内容的提问来源于stack exchange,提问作者Ricardo Tovar
相关产品推荐
相关产品推荐

