Angular 17+ 含Signals与Effects的Service测试问题解决
测试Angular Signal Effect触发的服务调用链问题
我有一个ServiceA,通过公开方法更新内部私有Signal,Signal值变化时会触发构造函数中定义的Effect,进而调用私有方法,最终调用ServiceB的公开方法。功能运行正常,但测试时无法验证整个调用链,测试总是失败,提示ServiceB的方法未被调用。
示例代码
ServiceA实现
@Injectable({ providedIn: 'root' }) export class ServiceA { private signalA = signal(0); constructor(private readonly serviceB: ServiceB) { effect(() => { const signalAValue = this.signalA(); this.privateMethodA(signalAValue); }); } public publicMethodA(value: number): void { this.signalA.set(value); } private privateMethodA(arg: number): void { this.serviceB.publicMethodB(arg); } }
测试代码
describe('ServiceA', () => { let serviceA: ServiceA; let serviceB: ServiceB; beforeEach(() => { TestBed.configureTestingModule({ providers: [ ServiceA, ServiceB ] }); serviceA = TestBed.inject(ServiceA); serviceB = TestBed.inject(ServiceB); }); it('should call publicMethodB of ServiceB when publicMethodA of ServiceA is called', fakeAsync(() => { jest.spyOn(serviceB, 'publicMethodB'); serviceA.publicMethodA(1); expect(serviceB.publicMethodB).toHaveBeenCalled(); })); });
测试失败信息
Expected number of calls: >= 1
Received number of calls: 0
问题原因
Angular的effect是异步执行的,当Signal更新后,Effect的回调不会立即同步执行,而是被加入到微任务队列中。在fakeAsync测试环境下,如果不手动触发微任务执行,断言会在Effect执行前就运行,导致检测不到ServiceB方法的调用。
解决方案
在fakeAsync测试中,调用tick()或flush()方法,手动推进时间并执行所有待处理的微任务,确保Effect完成执行后再进行断言。
修改后的测试代码
describe('ServiceA', () => { let serviceA: ServiceA; let serviceB: ServiceB; beforeEach(() => { TestBed.configureTestingModule({ providers: [ ServiceA, ServiceB ] }); serviceA = TestBed.inject(ServiceA); serviceB = TestBed.inject(ServiceB); }); it('should call publicMethodB of ServiceB when publicMethodA of ServiceA is called', fakeAsync(() => { const spy = jest.spyOn(serviceB, 'publicMethodB'); serviceA.publicMethodA(1); // 触发所有待执行的微任务,包括Effect的回调 tick(); expect(spy).toHaveBeenCalledWith(1); })); });
补充说明
tick()会模拟时间流逝,执行所有已排队的微任务,适合这种场景flush()会执行所有微任务和宏任务,效果更强,如果有其他异步操作也能处理- 也可以用
waitForAsync配合async/await,但fakeAsync + tick在服务测试中更简洁直观
内容的提问来源于stack exchange,提问作者Nenad
相关产品推荐
相关产品推荐

