Насмешка над маршрутом API в шпионской службе (с Жасмином)

#angular #typescript #mocking #jasmine #spy

Вопрос:

Я пытаюсь создать маршрут API в шпионской службе, используя Jasmine.

Я очень новичок в Angular, Typescript и Jasmine, поэтому я не могу сказать, чего мне не хватает в моем коде, должен ли я вставлять код в beforeEach или в свой собственный it('should do xyz...') и т. Д.

Я считаю , что должен запускать макет внутри beforeEach , но я сталкиваюсь с ошибкой с полезной нагрузкой (см. Примечания ниже).

технические характеристики:

 providers: [
   { provide: MyService, useValue: CommonServiceSpies.createHttpClientSpy()},
]

beforeEach(() => {
    fixture = TestBed.createComponent(ManagerComponent);

    const myVar = TestBed.inject(MyService) as jasmine.SpyObj<MyService>;
    
    const payload = 123 // I'd had an object that resembled the payload from the component.ts file, but it's not working with how the service was set up // Error received was: "Account of type Observable<{}> is not assignable to param of type 'Observable<number>'"

    myVar.GetRemainingAmount.and.returnValue(of(payload)); // Testing window err: "cannot read property 'and' of undefined"

    fixture.detectChanges();
});

it('should create', () => {
    expect(component).toBeTruthy();
});

 

сервис.ts:

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

    GetRemainingAmount(request: RemainingAmountRequest): Observable<number> {
        return this.http.post<number>('/some-route', request);
    }

 

менеджер-компонент.ts:

 constructor(
    public myService: MyService
  ) { } 

 hasRemainingSpend() : void {
    const payload: RemainingAmountRequest = {
      accountId: this.account.id,
      otherId: this.xyz?.id
    }

    this.myService.GetRemainingAmount(payload).subscribe((response: number) => {
      this.warningSpend = response;

      if (this.warningSpend < this.rate.value || this.warningSpend == null) {
        // call another func
        // this is working as expected
      }
    })

  }
 

Ответ №1:

Я не уверен, что CommonServiceSpies.createHttpClientSpy() это делает, но я могу предположить, что это создает HTTP-шпиона.

Это хороший ресурс для тестирования угловых блоков, но он также показывает, как имитировать внешние зависимости.

Я бы сделал:

 // before the first beforeEach, create a variable that will be a Spy Object
let mockMyService: jasmine.SpyObj<MyService>;
// Inside of the first beforeEach (TestBed.configureTestingModule),
// assign a value to the variable
// The first argument is a string for debugging purposes and the
// the second array of strings are public methods you would like to mock
mockMyService = jasmine.createSpyObj<MyService>('MyService', ['GetRemainingAmount']);
providers: [
   // provide the mock we just created
   { provide: MyService, useValue: mockMyService},
]

beforeEach(() => {
    fixture = TestBed.createComponent(ManagerComponent);
    // return an empty object for this method
    myService.GetRemainingAmount.and.returnValue(of({}));
   
    fixture.detectChanges();
});

it('should create', () => {
    expect(component).toBeTruthy();
});
 

Если вы не хотите этого делать, вы можете исправить то, что у вас есть, выполнив следующие действия:

Измените эту строку:

 myVar.GetRemainingAmount.and.returnValue(of(payload));
 

Для:

 spyOn(myVar, 'GetRemainingAmount').and.returnValue(of({}));