如何spyOn内部方法并返回指定值?测试中spyOn未生效排查
解决
spyOn未生效及toHaveBeenCalled断言失败的问题 我来帮你排查几个常见的原因,以及对应的解决办法:
1. 你Spy的实例和测试代码使用的不是同一个
这是最容易踩的坑——如果bdbPlatforms是通过依赖注入(比如Angular的TestBed)提供的,你可能不小心Spy了一个和测试代码实际使用的完全不同的实例。
解决办法:
确保你先获取到测试容器里的真实实例,再对它进行Spy操作:
describe('navigation provider: test', () => { let bdbPlatforms: BdbPlatforms; let navProvider: NavigationProvider; beforeEach(() => { TestBed.configureTestingModule({ providers: [NavigationProvider, BdbPlatforms] }); // 先拿到会被待测试代码实际使用的实例 bdbPlatforms = TestBed.inject(BdbPlatforms); // 对这个实例设置Spy spyOn(bdbPlatforms, 'isBrowser').and.returnValue(false); // 再获取待测试的Provider(确保它依赖的是已经被Spy的实例) navProvider = TestBed.inject(NavigationProvider); }); it('should trigger isBrowser check when executing method', () => { // 调用待测试的核心方法 navProvider.yourTargetTestMethod(); // 执行断言 expect(bdbPlatforms.isBrowser).toHaveBeenCalled(); }); });
2. Spy设置的时机太晚了
如果你的待测试逻辑(比如组件的ngOnInit、Provider的初始化代码)在Spy设置之前就已经执行了,那Spy自然捕获不到任何调用记录。
解决办法:
一定要在待测试代码执行之前完成Spy设置:
- 组件测试中,先Spy再调用
fixture.detectChanges()(第一次detectChanges会触发组件初始化) - Provider测试中,先Spy再获取Provider实例(避免Provider初始化阶段就调用了
isBrowser)
3. isBrowser不是普通的实例方法?
如果isBrowser是静态方法,那你需要Spy类本身而不是实例:
// 静态方法的Spy方式 spyOn(BdbPlatforms, 'isBrowser').and.returnValue(false); // 断言也要对应类的静态方法 expect(BdbPlatforms.isBrowser).toHaveBeenCalled();
如果isBrowser是一个getter属性(比如用get isBrowser() { ... }定义的),那要用spyOnProperty替代spyOn:
spyOnProperty(bdbPlatforms, 'isBrowser').and.returnValue(false); // 对于getter,你可以直接断言返回值,或者检查属性是否被访问 expect(bdbPlatforms.isBrowser).toBe(false);
快速排查小技巧
你可以在测试代码里打印bdbPlatforms.isBrowser,如果输出是SpyFunction,说明Spy成功了;如果还是原来的函数/属性,那肯定是Spy错了对象或者时机不对。
内容的提问来源于stack exchange,提问作者Jhonycage
相关产品推荐
相关产品推荐

