代码之家  ›  专栏  ›  技术社区  ›  Philip Mutua

如何在Jest中模拟location.back()方法调用进行角度组件测试?

  •  0
  • Philip Mutua  · 技术社区  · 2 年前

    我正在测试一个Angular组件,特别是 handleConformData 方法在 ManagePaymentsComponent ,使用Jest。该方法负责根据特定条件设置确认数据。我想确保这种方法的全面测试覆盖率,涵盖各种场景,包括是否满足某些条件。我已经介绍了大部分测试用例,但有一个没有涵盖。当 account 值是 null undefined 如下图所示,未涵盖。

    enter image description here

    Ts文件

    import { Location } from '@angular/common';
    import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core';
    import { MatSnackBar } from '@angular/material/snack-bar';
    import { Router } from '@angular/router';
    import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
    import moment from 'moment';
    import { take } from 'rxjs';
    import { SaveProduct } from 'src/app/core/interfaces';
    import { SaveInvestService } from 'src/app/core/services/save-invest/save-invest.service';
    import { StorageService } from 'src/app/core/services/storage/storage.service';
    import { BaseInvestComponent } from '../../base-invest.component';
    import {
      CreateInvestProductErrorModalComponent,
      InvestProductModalAction,
    } from '../../components/create-invest-product-error-modal/create-invest-product-error-modal.component';
    
    @Component({
      selector: 'app-manage-payments',
      templateUrl: './manage-payments.component.html',
      styleUrls: ['./manage-payments.component.scss'],
    })
    export class ManagePaymentsComponent extends BaseInvestComponent implements OnInit {
      account: any;
      accounts: any[] = [];
      confirmData = [];
      tryNotifyCount = 0;
      products!: SaveProduct[];
      unavailableDate: string = $localize`:@@loco\:64d080b85197317166074a02:Date-not-available`;
    
      constructor(
        @Inject(LOCALE_ID) private localeId: string,
        router: Router,
        modalService: NgbModal,
        saveInvestService: SaveInvestService,
        storageService: StorageService,
        snackbar: MatSnackBar,
        private location: Location
      ) {
        super(snackbar, saveInvestService, storageService, modalService, router);
        this.saveInvestService.currentPageHeader = $localize`:@@loco\:64afcd947dea13249f01fb52:Manage payments`;
      }
    
      ngOnInit(): void {
        this.saveInvestService.toggleStepperVisibility(true);
        this.handleConfirmData();
        this.getSavingsProducts();
      }
    
      openDeleteRecurringPayment() {
        this.router.navigateByUrl('invest/recurring-payments/delete');
      }
    
      private handleConfirmData(): void {
        const product = this.getSelectedProduct();
        this.account = product?.userData || {};
        if (!this.account) {
          this.location.back();
          return;
        }
        this.account.type = this.productType(product.productId);
    
        this.getRecurrentPaymentNextExecutionDate();
    
        const sourceAccount: any = this.account?.sourceAccount
          ? {
              titleTag: $localize`:@@loco\:62580d76e922220b5f540f12:Source-account`,
              value: `${this.account?.sourceAccount}`,
              description: this.account?.sourceAccountBalance
                ? $localize`:@@loco\:5f0714017799f92299271aa4:Account-balance` +
                  ` ${Number(this.account?.sourceAccountBalance || 0).toLocaleString(undefined, {
                    minimumFractionDigits: 2,
                    maximumFractionDigits: 2,
                  })} ${this.account?.accountCurrency}`
                : undefined,
            }
          : {};
    
        // Always reset 'userDataEdited'
        this.setSelectedProduct({ ...product, userData: this.account, userDataEdited: undefined });
    
        if (!this.account.recurring) {
          // Account without SI set
          this.confirmData = [
            sourceAccount,
            {
              titleTag: `Acc. ${this.account.accountNumber}`,
              value: `${this.account?.goalName || this.account.productName}`,
              description: `Balance: ${this.accountBalance(this.account)}`,
            },
          ];
          if (this.account?.type === 'goal') {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:642bc0055b11c37e7d72a392:Target-amount`,
              value: `${Number(this.account?.goalTargetAmount).toLocaleString()} ${
                this.account?.accountCurrency
              }`,
            });
            if (this.account?.targetDate) {
              this.confirmData.push({
                titleTag: $localize`:@@loco\:630ef7aa66acdc427a632e82:Info-text-Target-date`,
                value: `${moment(this.account.targetDate).format('ddd DD MMM YYYY')}`,
              });
            }
          }
          this.confirmData.push({
            titleTag: $localize`:@@loco\:625cec26795dae3aab31dbd4:Payment option`,
            value: $localize`:@@loco\:642bbf1dc9dcaf153107c328:Manual top up`,
          });
        } else {
          // Account has SI already set
          this.confirmData = [
            this.account?.paymentFrequency
              ? {
                  titleTag: $localize`:@@loco\:61c08648dfb1585223407592:Payment-Frequency`,
                  value: `${this.account?.paymentFrequency}`,
                  // description: `Every wednesday`,
                }
              : {},
            sourceAccount,
            {
              titleTag: $localize`:@@loco\:5f0724a875f9bc76f653e575:Account-Balance`,
              value: `${this.accountBalance(this.account)}`,
            },
            {
              titleTag: $localize`:@@loco\:642bbe7599aec22bcf558842:Start-payment-date`,
              value: `${moment(this.account.startDate).format('ddd DD MMM YYYY')}`,
            },
            {
              titleTag: $localize`:@@loco\:642c1f888c27446fa66baaf3:Info-text-End-payment-date`,
              value: `${moment(this.account.endDate).format('ddd DD MMM YYYY')}`,
            },
          ];
          if (
            this.account?.type === 'classic' &&
            this.account?.startDate &&
            this.account?.endDate &&
            this.account?.paymentFrequency
          ) {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:62dfb3755ce92e444e503212:Info-text-Number-of-payments`,
              value: `${this.getNumberOfPayments(
                new Date(this.account?.startDate),
                new Date(this.account?.endDate),
                this.account?.paymentFrequency.toLowerCase()
              )}`,
            });
          }
          if (this.account?.type === 'goal') {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:642bc0055b11c37e7d72a392:Target amount`,
              value: `${Number(
                this.account?.goalTargetAmount || this.account?.targetAmount
              ).toLocaleString()} ${this.account?.accountCurrency}`,
            });
            if (this.account?.targetDate) {
              this.confirmData.push({
                titleTag: $localize`:@@loco\:630ef7aa66acdc427a632e82:Target date`,
                value: `${moment(this.account.targetDate).format('DD MMM YYYY')}`,
              });
            }
          }
        }
        this.confirmData = this.confirmData.filter((e) => Object.keys(e).length);
      }
    
     
    }
    

    测试用例

    import { Location } from '@angular/common';
    import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core';
    import { MatSnackBar } from '@angular/material/snack-bar';
    import { Router } from '@angular/router';
    import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
    import moment from 'moment';
    import { take } from 'rxjs';
    import { SaveProduct } from 'src/app/core/interfaces';
    import { SaveInvestService } from 'src/app/core/services/save-invest/save-invest.service';
    import { StorageService } from 'src/app/core/services/storage/storage.service';
    import { BaseInvestComponent } from '../../base-invest.component';
    import {
      CreateInvestProductErrorModalComponent,
      InvestProductModalAction,
    } from '../../components/create-invest-product-error-modal/create-invest-product-error-modal.component';
    
    @Component({
      selector: 'app-manage-payments',
      templateUrl: './manage-payments.component.html',
      styleUrls: ['./manage-payments.component.scss'],
    })
    export class ManagePaymentsComponent extends BaseInvestComponent implements OnInit {
      account: any;
      accounts: any[] = [];
      confirmData = [];
      tryNotifyCount = 0;
      products!: SaveProduct[];
      unavailableDate: string = $localize`:@@loco\:64d080b85197317166074a02:Date-not-available`;
    
      constructor(
        @Inject(LOCALE_ID) private localeId: string,
        router: Router,
        modalService: NgbModal,
        saveInvestService: SaveInvestService,
        storageService: StorageService,
        snackbar: MatSnackBar,
        private location: Location
      ) {
        super(snackbar, saveInvestService, storageService, modalService, router);
        this.saveInvestService.currentPageHeader = $localize`:@@loco\:64afcd947dea13249f01fb52:Manage payments`;
      }
    
      ngOnInit(): void {
        this.saveInvestService.toggleStepperVisibility(true);
        this.handleConfirmData();
        this.getSavingsProducts();
      }
    
      openDeleteRecurringPayment() {
        this.router.navigateByUrl('invest/recurring-payments/delete');
      }
    
      private handleConfirmData(): void {
        const product = this.getSelectedProduct();
        this.account = product?.userData || {};
        if (!this.account) {
          this.location.back();
          return;
        }
        this.account.type = this.productType(product.productId);
    
        this.getRecurrentPaymentNextExecutionDate();
    
        const sourceAccount: any = this.account?.sourceAccount
          ? {
              titleTag: $localize`:@@loco\:62580d76e922220b5f540f12:Source-account`,
              value: `${this.account?.sourceAccount}`,
              description: this.account?.sourceAccountBalance
                ? $localize`:@@loco\:5f0714017799f92299271aa4:Account-balance` +
                  ` ${Number(this.account?.sourceAccountBalance || 0).toLocaleString(undefined, {
                    minimumFractionDigits: 2,
                    maximumFractionDigits: 2,
                  })} ${this.account?.accountCurrency}`
                : undefined,
            }
          : {};
    
        // Always reset 'userDataEdited'
        this.setSelectedProduct({ ...product, userData: this.account, userDataEdited: undefined });
    
        if (!this.account.recurring) {
          // Account without SI set
          this.confirmData = [
            sourceAccount,
            {
              titleTag: `Acc. ${this.account.accountNumber}`,
              value: `${this.account?.goalName || this.account.productName}`,
              description: `Balance: ${this.accountBalance(this.account)}`,
            },
          ];
          if (this.account?.type === 'goal') {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:642bc0055b11c37e7d72a392:Target-amount`,
              value: `${Number(this.account?.goalTargetAmount).toLocaleString()} ${
                this.account?.accountCurrency
              }`,
            });
            if (this.account?.targetDate) {
              this.confirmData.push({
                titleTag: $localize`:@@loco\:630ef7aa66acdc427a632e82:Info-text-Target-date`,
                value: `${moment(this.account.targetDate).format('ddd DD MMM YYYY')}`,
              });
            }
          }
          this.confirmData.push({
            titleTag: $localize`:@@loco\:625cec26795dae3aab31dbd4:Payment option`,
            value: $localize`:@@loco\:642bbf1dc9dcaf153107c328:Manual top up`,
          });
        } else {
          // Account has SI already set
          this.confirmData = [
            this.account?.paymentFrequency
              ? {
                  titleTag: $localize`:@@loco\:61c08648dfb1585223407592:Payment-Frequency`,
                  value: `${this.account?.paymentFrequency}`,
                  // description: `Every wednesday`,
                }
              : {},
            sourceAccount,
            {
              titleTag: $localize`:@@loco\:5f0724a875f9bc76f653e575:Account-Balance`,
              value: `${this.accountBalance(this.account)}`,
            },
            {
              titleTag: $localize`:@@loco\:642bbe7599aec22bcf558842:Start-payment-date`,
              value: `${moment(this.account.startDate).format('ddd DD MMM YYYY')}`,
            },
            {
              titleTag: $localize`:@@loco\:642c1f888c27446fa66baaf3:Info-text-End-payment-date`,
              value: `${moment(this.account.endDate).format('ddd DD MMM YYYY')}`,
            },
          ];
          if (
            this.account?.type === 'classic' &&
            this.account?.startDate &&
            this.account?.endDate &&
            this.account?.paymentFrequency
          ) {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:62dfb3755ce92e444e503212:Info-text-Number-of-payments`,
              value: `${this.getNumberOfPayments(
                new Date(this.account?.startDate),
                new Date(this.account?.endDate),
                this.account?.paymentFrequency.toLowerCase()
              )}`,
            });
          }
          if (this.account?.type === 'goal') {
            this.confirmData.push({
              titleTag: $localize`:@@loco\:642bc0055b11c37e7d72a392:Target amount`,
              value: `${Number(
                this.account?.goalTargetAmount || this.account?.targetAmount
              ).toLocaleString()} ${this.account?.accountCurrency}`,
            });
            if (this.account?.targetDate) {
              this.confirmData.push({
                titleTag: $localize`:@@loco\:630ef7aa66acdc427a632e82:Target date`,
                value: `${moment(this.account.targetDate).format('DD MMM YYYY')}`,
              });
            }
          }
        }
        this.confirmData = this.confirmData.filter((e) => Object.keys(e).length);
      }
    
      openAddRecurringPayment() {
        this.router.navigateByUrl('invest/recurring-payments/edit/payment-details');
      }
    
      editRecurringAccount(): void {
        let selectedProduct: any = this.products.find((p) => p?.productId === this.account.productId);
        this.setSelectedProduct(selectedProduct);
        selectedProduct = this.getSelectedProduct();
        selectedProduct.userData = this.account;
        const userData = selectedProduct.userData || {};
        selectedProduct = {
          ...selectedProduct,
          userData,
        };
        this.setSelectedProduct(selectedProduct);
        // console.log(this.getSelectedProduct()); return;
        this.router.navigateByUrl('invest/recurring-payments/edit/payment-details');
      }
    
      private accountBalance(account: any): string {
        return `${Number(account?.accountBalance || '0').toLocaleString(undefined, {
          minimumFractionDigits: 2,
          maximumFractionDigits: 2,
        })} ${account?.accountCurrency}`;
      }
    
      recurrentAmount(account: any): string {
        return `${Number(account?.recurrentAmount || '0').toLocaleString(undefined, {
          minimumFractionDigits: 2,
          maximumFractionDigits: 2,
        })} ${account?.accountCurrency}`;
      }
    
      protected getSavingsProducts(): void {
        this.saveInvestService
          .getSavingsProducts(false, false)
          .pipe(take(1))
          .subscribe({
            next: (resp) => {
              if (resp?.statusCode === '00') {
                this.mapProducts(resp.responseObject);
                this.tryNotifyCount = 0;
              } else {
                this.handleProductErrors();
              }
            },
            error: (error) => {
              this.handleProductErrors();
            },
          });
      }
    
      private mapProducts(data: SaveProduct[]): void {
        this.products = data.map((p: SaveProduct) => {
          const metadata = this.getProductMetadata(p?.productId);
          return {
            productId: p?.productId,
            name: p?.name,
            illustrationLink: p?.illustrationLink,
            minimumDeposits: p?.minimumDeposits,
            shortDescription: p?.shortDescription,
            longDescription: p?.longDescription || [],
            productCategories: p?.productCategories || [],
            slug: metadata?.slug,
            terms: metadata?.terms,
            disabled: metadata?.disabled,
            show: metadata?.show,
            rates: metadata?.rates,
          };
        });
      }
    
      private handleProductErrors(): any {
        const errOptions = {
          title: $localize`:@@loco\:61fbeddfe4fc547a26382c34:We're sorry`,
          message: $localize`:@@loco\:6214cffea2191e102167dad2:Something went wrong on our side. Please try again.`,
          component: CreateInvestProductErrorModalComponent,
          modal: {
            windowClass: 'invest-create-error-modal',
            centered: true,
            backdrop: 'static',
            keyboard: false,
          },
          options: {
            showCloseButton: true,
            actions: [InvestProductModalAction.tryagain],
            subscription: (action: InvestProductModalAction) => {
              if (action == InvestProductModalAction.tryagain) {
                this.tryNotifyCount++;
                if (this.tryNotifyCount < 3) this.getSavingsProducts();
                else {
                  this.tryNotifyCount = 0;
                  this.router.navigateByUrl('/invest');
                }
                modal.dismiss();
              } else {
                modal.dismiss();
              }
            },
          },
        };
        this.modalService.dismissAll();
        const modal = this.notifyModal(errOptions);
      }
    
      name(account: any): string {
        return account?.type === 'goal'
          ? $localize`:@@loco\:5f0725f26e3a005a42063ab3:Goal` + ` - ${account?.goalName}`
          : account.productName;
      }
    
      private getRecurrentPaymentNextExecutionDate(): void {
        if (
          !this.account?.recurring ||
          // this.account?.nextPaymentDate ||
          (this.account?.type !== 'classic' && this.account?.type !== 'goal')
        )
          return;
    
        const payload: any[] = [
          {
            savingsAccount: this.account?.accountNumber,
            productId: this.account?.productId,
            customerId: this.account?.cif,
            bankId: this.account?.bankId,
          },
        ];
        this.saveInvestService
          .getRecurrentPaymentNextExecutionDate(payload)
          .pipe(take(1))
          .subscribe({
            next: (resp) => {
              if (resp.successful && resp.responseObject?.length)
                this.account = Object.assign(this.account, {
                  nextPaymentDate: resp.responseObject[0].nextPaymentDate
                    ? `${moment(new Date(resp.responseObject[0].nextPaymentDate)).format(
                        'ddd DD MMM YYYY'
                      )}`
                    : '',
                });
            },
          });
      }
    
      private productType(productId: number): string {
        let type: string;
        switch (productId) {
          case 2:
            type = 'classic';
            break;
          case 3:
            type = 'goal';
            break;
          default:
            break;
        }
        return type;
      }
    }
    

    测试用例

    import { ComponentFixture, TestBed } from '@angular/core/testing';
    
    import { HttpClientModule } from '@angular/common/http';
    import { HttpClientTestingModule } from '@angular/common/http/testing';
    import { MatSnackBarModule } from '@angular/material/snack-bar';
    import { Router } from '@angular/router';
    import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
    import { of, throwError } from 'rxjs';
    import { SaveProduct } from 'src/app/core/interfaces';
    import { SaveInvestService, StorageService } from 'src/app/core/services';
    import { InvestProductModalAction } from '../../components/create-invest-product-error-modal/create-invest-product-error-modal.component';
    import { ManagePaymentsComponent } from './manage-payments.component';
    
    describe('ManagePaymentsComponent', () => {
      let component: ManagePaymentsComponent;
      let fixture: ComponentFixture<ManagePaymentsComponent>;
      let saveInvestService: SaveInvestService;
      let saveInvestServiceMock: jest.SpyInstance;
      let storageServiceMock: StorageService;
    
      let modalService: NgbModal;
    
      const mockRouter = { navigate: jest.fn(), navigateByUrl: jest.fn() };
    
      const mockLocation = { back: jest.fn() };
    
      const mockModal = {
        dismiss: jest.fn(),
        close: jest.fn(),
        open: jest.fn(),
        dismissAll: jest.fn(),
      };
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ManagePaymentsComponent],
          imports: [HttpClientModule, HttpClientTestingModule, MatSnackBarModule],
          providers: [
            { provide: NgbModal },
            { provide: Router, useValue: mockRouter },
            { provide: Location, useValue: mockLocation },
          ],
        }).compileComponents();
        saveInvestService = TestBed.inject(SaveInvestService);
        storageServiceMock = TestBed.inject(StorageService);
    
        modalService = TestBed.inject(NgbModal);
      });
    
      beforeEach(() => {
        fixture = TestBed.createComponent(ManagePaymentsComponent);
        component = fixture.componentInstance;
        jest
          .spyOn(component, 'getSelectedProduct')
          .mockReturnValue({ userData: { accountCurrency: 'USD' } });
        // mock products
        const mockProducts: SaveProduct[] = [
          {
            productId: 1,
            name: 'Product A',
            minimumDeposits: [{ currency: 'USD', minimumAmount: 100 }],
            shortDescription: 'Short description for Product A',
            terms: 'Terms and conditions for Product A',
            disabled: false,
            show: true,
          },
          {
            productId: 2,
            name: 'Product B',
            minimumDeposits: [{ currency: 'EUR', minimumAmount: 50 }],
            shortDescription: 'Short description for Product B',
            terms: 'Terms and conditions for Product B',
            disabled: false,
            show: true,
          },
        ];
    
        component.products = mockProducts;
    
        component.account = {
          productId: 2,
          userData: {
            name: 'John Doe',
            age: 30,
          },
        };
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    
      describe('handleConfirmData', () => {
        it('should navigate back if account is undefined', () => {
          jest.spyOn(component, 'getSelectedProduct').mockReturnValue({});
          const lockationSpy = jest.spyOn(mockLocation, 'back');
    
          // Mocking this.account to always equal {}
          component['account'] = {};
    
          component['handleConfirmData']();
    
          expect(component.account).toEqual({});
          expect(lockationSpy).toHaveBeenCalled();
          //   expect(component.confirmData.length).toBe(0);
        });
    
        it('should set confirmData correctly for account without recurring payment (goal)', () => {
          const mockProduct = {
            productId: 3,
            userData: {
              accountNumber: '1234567890',
              goalName: 'My Goal',
              accountBalance: 1000,
              accountCurrency: 'USD',
              goalTargetAmount: 5000,
              targetDate: new Date('2024-12-31'),
              type: 'goal',
            },
          };
          jest.spyOn(component, 'getSelectedProduct').mockReturnValue(mockProduct);
          jest.spyOn(component as any, 'productType').mockReturnValue('goal');
          jest.spyOn(component as any, 'accountBalance').mockReturnValue('1,000.00 USD');
    
          component['handleConfirmData']();
    
          expect(component.confirmData).toEqual([
            { titleTag: 'Acc. 1234567890', value: 'My Goal', description: 'Balance: 1,000.00 USD' },
            { titleTag: 'Target-amount', value: '5,000 USD' },
            { titleTag: 'Info-text-Target-date', value: 'Tue 31 Dec 2024' },
            { titleTag: 'Payment option', value: 'Manual top up' },
          ]);
        });
    
        it('should set confirmData correctly for account without recurring payment (classic)', () => {
          const mockProduct = {
            productId: 2,
            userData: {
              accountNumber: '1234567890',
              productName: 'Classic Account',
              accountBalance: 1000,
              accountCurrency: 'USD',
              type: 'classic',
            },
          };
          jest.spyOn(component, 'getSelectedProduct').mockReturnValue(mockProduct);
          jest.spyOn(component as any, 'productType').mockReturnValue('classic');
          jest.spyOn(component as any, 'accountBalance').mockReturnValue('1,000.00 USD');
    
          component['handleConfirmData']();
    
          expect(component.confirmData).toEqual([
            {
              titleTag: 'Acc. 1234567890',
              value: 'Classic Account',
              description: 'Balance: 1,000.00 USD',
            },
            { titleTag: 'Payment option', value: 'Manual top up' },
          ]);
        });
    
        it('should set confirmData correctly for account with recurring payment (goal)', () => {
          const mockProduct = {
            productId: 3,
            userData: {
              accountNumber: '1234567890',
              goalName: 'My Goal',
              accountBalance: 2000,
              accountCurrency: 'USD',
              recurring: true,
              paymentFrequency: 'Weekly',
              startDate: '2023-01-01',
              endDate: '2023-12-31',
              goalTargetAmount: 10000,
              targetDate: '2024-06-30',
              type: 'goal',
            },
          };
          jest.spyOn(component, 'getSelectedProduct').mockReturnValue(mockProduct);
          jest.spyOn(component as any, 'productType').mockReturnValue('goal');
          jest.spyOn(component as any, 'accountBalance').mockReturnValue('2,000.00 USD');
    
          component['handleConfirmData']();
    
          expect(component.confirmData).toEqual([
            { titleTag: 'Payment-Frequency', value: 'Weekly' },
            { titleTag: 'Account-Balance', value: '2,000.00 USD' },
            { titleTag: 'Start-payment-date', value: 'Sun 01 Jan 2023' },
            { titleTag: 'Info-text-End-payment-date', value: 'Sun 31 Dec 2023' },
            { titleTag: 'Target amount', value: '10,000 USD' },
            { titleTag: 'Target date', value: '30 Jun 2024' },
          ]);
        });
    
        it('should set confirmData correctly for account with recurring payment (classic)', () => {
          const mockProduct = {
            productId: 2,
            userData: {
              accountNumber: '1234567890',
              productName: 'Classic Account',
              accountBalance: 2000,
              accountCurrency: 'USD',
              recurring: true,
              paymentFrequency: 'Monthly',
              startDate: '2023-01-01',
              endDate: '2023-12-31',
              type: 'classic',
            },
          };
          jest.spyOn(component, 'getSelectedProduct').mockReturnValue(mockProduct);
          jest.spyOn(component as any, 'productType').mockReturnValue('classic');
          jest.spyOn(component as any, 'accountBalance').mockReturnValue('2,000.00 USD');
          jest.spyOn(component, 'getNumberOfPayments').mockReturnValue(12);
    
          component['handleConfirmData']();
    
          expect(component.confirmData).toEqual([
            { titleTag: 'Payment-Frequency', value: 'Monthly' },
            { titleTag: 'Account-Balance', value: '2,000.00 USD' },
            { titleTag: 'Start-payment-date', value: 'Sun 01 Jan 2023' },
            { titleTag: 'Info-text-End-payment-date', value: 'Sun 31 Dec 2023' },
            { titleTag: 'Info-text-Number-of-payments', value: '12' },
          ]);
        });
      });
    
    });
    

    输出

    enter image description here

    0 回复  |  直到 2 年前
        1
  •  1
  •   Naren Murali    2 年前

    请设置 account undefined ,而不是 {} 在if条件内, {} 将评估为true,因此它不会进入if!

    it('should navigate back if account is undefined', () => {
      jest.spyOn(component, 'getSelectedProduct').mockReturnValue({});
      const lockationSpy = jest.spyOn(component['location'], 'back'); // changed here!
    
      // Mocking this.account to always equal undefined
      component['account'] = undefined; // null can also be used!
    
      component['handleConfirmData']();
    
      expect(component.account).toEqual(undefined);
      expect(lockationSpy).toHaveBeenCalled();
    });
    

    你的测试用例很好,我注意到在代码中,你也需要对实际函数执行上述步骤!,因为代码的编写方式,永远不会出现它进入if条件的情况,因为任何false条件都会回退到 {} 所以如果永远不会是真的!

     private handleConfirmData(): void {
        const product = this.getSelectedProduct();
        this.account = product?.userData; // changed here!
        if (!this.account) {
          this.location.back();
          return;
        }
    
    推荐文章