Angular Firebase测试:Mock getDownloadURL方法失败问题求助
解决Mock AngularFireStorage的getDownloadURL方法报错问题
你的错误根源很明确:你模拟的AngularFireStorage实例返回的ref对象没有实现getDownloadURL方法,导致调用时抛出类型错误。下面是几种可行的修复方案,按场景选择:
方案1:直接Mock链式调用(适合简单测试场景)
在测试文件中,需要完整模拟storage.ref()返回的对象,以及它的getDownloadURL()方法(注意这个方法实际返回Promise,因为AngularFireStorage的getDownloadURL本身是异步的)。
示例测试代码:
import { TestBed } from '@angular/core/testing'; import { TownhallPictureService } from './townhall-picture.service'; import { AngularFireStorage } from '@angular/fire/compat/storage'; import { from, Observable } from 'rxjs'; // 模拟AngularFireStorage的ref方法 const mockAngularFireStorage = jasmine.createSpyObj('AngularFireStorage', ['ref']); // 模拟ref返回的存储引用对象,包含getDownloadURL方法 const mockStorageRef = jasmine.createSpyObj('StorageReference', ['getDownloadURL']); // 设置链式调用的返回逻辑 mockAngularFireStorage.ref.and.returnValue(mockStorageRef); // 让getDownloadURL返回一个已resolve的Promise,对应你期望的图片URL mockStorageRef.getDownloadURL.and.returnValue(Promise.resolve('https://example.com/townhall-1.png')); describe('TownhallPictureService', () => { let service: TownhallPictureService; beforeEach(() => { TestBed.configureTestingModule({ providers: [ TownhallPictureService, { provide: AngularFireStorage, useValue: mockAngularFireStorage } ] }); service = TestBed.inject(TownhallPictureService); }); it('should return townhall level by valid input', (done) => { service.getTownHallPicture(1).subscribe(url => { expect(url).toBe('https://example.com/townhall-1.png'); done(); // 因为是Observable,需要用done通知测试完成 }); }); });
方案2:使用AngularFire官方测试工具(更贴近真实场景)
如果你引入了AngularFire的测试模块,可以用它来更优雅地mock存储服务:
import { TestBed } from '@angular/core/testing'; import { TownhallPictureService } from './townhall-picture.service'; import { AngularFireStorage, AngularFireStorageModule } from '@angular/fire/compat/storage'; import { AngularFireTestingModule } from '@angular/fire/compat/testing'; describe('TownhallPictureService', () => { let service: TownhallPictureService; let storage: AngularFireStorage; beforeEach(() => { TestBed.configureTestingModule({ imports: [AngularFireTestingModule, AngularFireStorageModule], providers: [TownhallPictureService] }); service = TestBed.inject(TownhallPictureService); storage = TestBed.inject(AngularFireStorage); // 直接mock ref方法的返回值,包含getDownloadURL逻辑 spyOn(storage, 'ref').and.returnValue({ getDownloadURL: () => Promise.resolve('https://example.com/townhall-1.png') } as any); }); it('should return townhall level by valid input', (done) => { service.getTownHallPicture(1).subscribe(url => { expect(url).toBe('https://example.com/townhall-1.png'); done(); }); }); });
额外注意点
- 检查你的服务代码:
getDownloadURL返回的是Promise,需要用from操作符把它转换成Observable,否则你的方法返回的Observable可能无法正常触发:// 修正服务中的转换逻辑 import { from, Observable, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; getTownHallPicture(townhall: number): Observable<string | null> { switch (townhall) { case 1: this.ref = this.storage.ref('path-to-townhall-1-img'); return from(this.ref.getDownloadURL()).pipe( catchError(() => of(null)) // 捕获错误返回null,符合你的返回类型定义 ); // 其他等级的case逻辑... default: return of(null); } }
内容的提问来源于stack exchange,提问作者MarcoLe
相关产品推荐
相关产品推荐

