Jasmine spyOn依赖注入服务单元测试断言失败问题求助
Jasmine测试构造函数注入依赖问题排查与修复
核心问题分析
第二个测试断言失败的直接原因是你mock了被测方法getAccount本身:
spyOn(service, 'getAccount').and.returnValue(Promise.resolve(accountData));
这段代码直接替换了AccountService.getAccount的原始实现,导致原方法里的权限校验逻辑(调用authorityService.hasAuthority)完全没有被执行,自然触发hasAuthority从未被调用的断言失败。
解决方案
要测试getAccount的真实逻辑,不能mock它本身,而是要mock它的依赖(ApiService的get方法),同时保持对authorityService.hasAuthority的spy,确保权限校验逻辑被执行。
修正后的测试代码
it('should return the account if the permissions are set', async () => { const accountData = { firstName: 'Test', lastName: "tester" } as Account; // 1. 保留对权限服务的spy,让它返回true spyOn(authorityServiceDependency, 'hasAuthority').withArgs(Authority.PERM_ACCOUNT_READ).and.returnValue(true); // 2. 调用被测方法 const account = await service.getAccount(); // 3. 验证权限校验被触发 expect(authorityServiceDependency.hasAuthority).toHaveBeenCalledWith(Authority.PERM_ACCOUNT_READ); // 4. 拦截ApiService的请求并返回预设数据 const req = httpTestingController.expectOne('/admin/rest/account'); expect(req.request.method).toBe('GET'); req.flush(accountData); // 5. 验证返回结果正确 expect(account).not.toBeNull(); expect(account?.firstName).toEqual("Test"); expect(account?.lastName).toEqual("tester"); // 确保所有请求都被处理 httpTestingController.verify(); });
关键调整说明
- 移除了对
service.getAccount的spy,让原始方法逻辑完整执行 - 使用
async/await处理异步逻辑,避免回调嵌套导致的断言时机问题 - 用
httpTestingController.expectOne精准拦截API请求,返回预设的账户数据 - 增加
httpTestingController.verify()确保没有未处理的请求
关于Stub类的使用说明
你当前用authorityServiceStub类替换真实服务的方式是正确的,不过也可以用更简洁的useValue方式直接创建对象,无需定义类:
{ provide: AuthorityService, useValue: { hasAuthority: () => false } }
两种方式都能达到替换依赖的目的,根据代码复杂度选择即可。
额外测试注意事项
- 测试异步方法时,优先使用
async/await,代码更易读且能确保断言在异步操作完成后执行 - 不要mock被测对象的方法,要mock它的依赖服务,这样才能测试真实业务逻辑
- 每次测试后,
HttpTestingController会自动清理,但主动调用verify()能提前发现未处理的请求问题
内容的提问来源于stack exchange,提问作者Stiley
相关产品推荐
相关产品推荐

