简体   繁体   English

如何在 Angular 中模拟查询参数以进行服务测试?

[英]How to mock a queryParam for a service testing in Angular?

I am trying to test an observable from a service in Angular, which depends on the value of a queryParam.我正在尝试从 Angular 中的服务测试可观察的,这取决于 queryParam 的值。

I'm very stuck when trying to mock the queryParam in order to be able to perform the test for the observable.在尝试模拟 queryParam 以便能够对 observable 执行测试时,我非常卡住。

I have tried different approaches, but I cannot get to implement the queryParam value.我尝试了不同的方法,但我无法实现 queryParam 值。

This is the service:这是服务:

import { Injectable } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CarService {
  private readonly _car$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(this.carStatus);

  constructor(private route: ActivatedRoute) {}

  public get car$(): Observable<boolean> {
    return this._car$.asObservable();
  }

  private get carStatus(): boolean {
    const isHybrid = this.route.snapshot.queryParamMap.get('hybrid') === 'true';
    if (isHybrid) return true;
    return false;
  }
}

These are the different approaches for the test file:这些是测试文件的不同方法:

Option 1选项1

import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';

import { CarService } from './carService.service';


describe('CarService', () => {
  let service: CarService;
  let route: ActivatedRouteSnapshot;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      providers: [CarService],
    });
    route = new ActivatedRouteSnapshot();
  });

  describe('When there is a hybrid car', () => {
    it('should enable the electric mode', (done) => {
      route.queryParams = {
        hybrid: 'true',
      };
      service = TestBed.inject(CarService);

      service.car$.subscribe((value: boolean) => {
        expect(value).toBe(true);
        done();
      });
    });
  });

  describe('When the car is not hybrid', () => {
    it('should NOT enable the electric mode', (done) => {
      route.queryParams = {
        hybrid: 'false',
      };
      service = TestBed.inject(CarService);

      service.car$.subscribe((value: boolean) => {
        expect(value).toBe(false);
        done();
      });
    });
  });

Option 2选项 2

import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';

import { CarService } from './carService.service';


describe('CarService', () => {
  let service: CarService;
  let route: ActivatedRouteSnapshot;

    beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      providers: [
        CarService,
        {
          provide: ActivatedRouteSnapshot,
          useValue: {
            snapshot: {
              queryParams: {
               hybrid: ‘true’,
              },
            },
          },
        },
      ],
    });
    route = TestBed.inject(ActivatedRouteSnapshot);
    service = TestBed.inject(CarService);
  });

  describe('When there is a hybrid car', () => {
    it('should enable the electric mode', (done) => {

      service.car$.subscribe((value: boolean) => {
        expect(value).toBe(true);
        done();
      });
    });
  });

Option 3 using spyOn选项 3 使用 spyOn

 describe('When there is a hybrid car', () => {
    it('should enable the electric mode', (done) => {
       const route = new ActivatedRouteSnapshot();
       spyOn(route.queryParamMap, 'get').and.returnValue('true');

       service = TestBed.inject(CarService);

     service.car$.subscribe((value: boolean) => {
        expect(value).toBe(true);
        done();
      });
    });
  });

I also tried to implement an ActivatedRouteStub like in the documentation here ( https://angular.io/guide/testing-components-scenarios#routed-components ), but I get to the same point as in the previous options.我还尝试在此处的文档中实现 ActivatedRouteStub( https://angular.io/guide/testing-components-scenarios#routed-components ),但我得到的点与前面的选项相同。 The get carStatus() in the service can never read the queryParam, because it's empty.服务中的 get carStatus() 永远无法读取 queryParam,因为它是空的。

If someone could help me with this, I'd be very grateful.如果有人可以帮助我,我将不胜感激。

Try this (we are using option 1):试试这个(我们使用选项 1):

import { TestBed } from '@angular/core/testing';

import { CarService } from './carService.service';


describe('CarService', () => {
  let service: CarService;
  let route: ActivatedRoute;
  let queryParamMapGet: jasmine.Spy;

  beforeEach(() => {
    // create a spy for the get method
    queryParamMapGet = jasmine.createSpy('queryParamMapGet');
    TestBed.configureTestingModule({
      providers: [CarService
        { 
          provide: ActivatedRoute, 
          useValue: { 
           snapshot: {
              queryParamMap: {
                        get: queryParamMapGet // assign it to the get spy
              } 
          } 
         } 
        }
      ],
    });
  });

  describe('When there is a hybrid car', () => {
    it('should enable the electric mode', (done) => {
      // return true for the get value
      queryParamMapGet.and.returnValue('true');

      service = TestBed.inject(CarService);

      service.car$.subscribe((value: boolean) => {
        expect(value).toBe(true);
        done();
      });
    });
  });

  describe('When the car is not hybrid', () => {
    it('should NOT enable the electric mode', (done) => {
      // return false for the get value
      queryParamMapGet.and.returnValue('true');

      service = TestBed.inject(CarService);

      service.car$.subscribe((value: boolean) => {
        expect(value).toBe(false);
        done();
      });
    });
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM