Angular 单元测试:Observable 未返回结果

Angular Unit Testing: Observable not returning results

我正在开发一个旧的 Angular 应用程序并尝试对功能按预期工作进行单元测试。

我只是想测试一个函数 returns 是否是正确的 http 请求,但测试无法读取可观察对象。

import {HttpClient} from '@angular/common/http';

@Injectable()
export class MyService {
  constructor(private http: HttpClient) {}

  getUrl() {
     //lots of logic to determine which url to get

     return this.http.put(url, null, { headers: requestHeaders, withCredentials: true 
     }).pipe(
      map((response: any) => {
        return response;
     }));
  }

}

有没有办法测试这个 getUrl 函数的结果?

如果我简单地记录这个函数的结果,我会得到一个可观察的。

Observable{_isScalar: false, source: Observable{_isScalar: false, source: Observable{_isScalar: ..., source: ..., operator: ...}, operator: MapOperator{project: ..., thisArg: ...}}, operator: CatchOperator{selector: handleError(error) { ... }, caught: Observable{_isScalar: ..., source: ..., operator: ...}}}

如果我订阅这个可观察对象,什么也不会发生。

let test = null;
service.getUrl().subscribe((value) => {
  test = value
});

console.log('test result', test);

这将记录为空。

如果有任何关于如何获得此函数结果的建议,我将不胜感激。谢谢

Angular 中有多种单元测试服务方法。 你可以在这里阅读:Testing HTTP Services

另一种方法是在您的 *.spec.ts 文件中创建模拟服务。

const MOCK_GET_URL_RESPONSE = 'test';

export class MockService() {
    // Implement service functions here
    getUrl(): Observable<any> {
        return of(MOCK_GET_URL_RESPONSE);
    }
}

describe('ABCComponent', () => {
    let component: ABCComponent;
    let fixture: ComponentFixture<ABCComponent>;
    let service: MockService;

    beforeEach(async () => {
        await TestBed.configureTestingModule({
            declarations: [ABCComponent],
            imports: [CommonModule, HttpClientTestingModule],
            // Provide your service and indicate which
            // class is to be used to mock it
            providers: [{ provide: MyService, useClass: MockService }],
        }).compileComponents();
    });

    it('should create', () => {
        service.getUrl().subscribe((res) => {
            console.log(res); // test
            expect(res).not.toBeNull(); // true
        });
    });
});

如果您选择使用模拟服务进行测试,通常最好定义响应的数据类型。因此,将您的 API 响应映射到一个类型而不是 any