在 Angular ng 测试中调用服务的方法

Methods in calling a service in Angular ng testing

提问人:Maguzu 提问时间:11/17/2023 更新时间:11/17/2023 访问量:17

问:

嗨,我是 Angular 的新手,我很难在我的单元测试脚本中解决这个问题。 我收到此错误“错误:预期已调用间谍createOperator。

你能给我一些关于如何正确做到这一点的建议吗?一些例子就可以了

顺便说一句,我的 angular 版本是 v16.14

单元测试:

describe('ComponentA', () => {
  let component: ComponentA;
  let fixture: ComponentFixture<ComponentA>;
  let ServiceA: ServiceA;
  let toast: ToastService;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [
        ComponentA
      ],
      imports: [
        TestingModule,
      ],
      providers: [
        {
          provide: MAT_DIALOG_DATA,
          useValue: {
            user: {},
            companyId: 1
          }
        },
        {
          provide: MatDialogRef,
          useValue: {
            close: () => of(true)
          }
        }
      ],
      schemas: [NO_ERRORS_SCHEMA]
    })
    .compileComponents();

    fixture = TestBed.createComponent(ComponentA);
    component = fixture.componentInstance;
    ServiceA = TestBed.inject(ServiceA);
    el = fixture.debugElement;
    toast = TestBed.inject(ToastService);
  }));

  fit('should create operator', () => {
    component.data.user = null;
    component.user = null;

    fixture.detectChanges();

    const payload = {
      user: {
        first_name: 'Test',
        last_name: 'Tester', 
        email: '[email protected]',
      },
      roles: [
        [['operator'],],
      ]
    };

    component.userForm.patchValue(payload);

    const response = {
      status: 'success',
      code: 201,
      message: 'Successfully Created a Operator!'
    };
    
    spyOn(ServiceA, 'createOperator').withArgs(payload).and.returnValue(of(response));
    const submitSpy = spyOn(component, 'onSubmit').and.callThrough();
    const toastSpy = spyOn(toast, 'notifyAction')
      .and
      .callThrough();

    fixture.detectChanges();
    component.onSubmit();

    
    expect(ServiceA.createOperator).toHaveBeenCalled();
    expect(component.onSubmit).toHaveBeenCalled();
    expect(toastSpy).toHaveBeenCalled();
  });

});

元件:

onSubmit(): any {
  if (this.userForm.invalid) {
    return;
  }

  this.loading = true;
  const values = this.userForm.value;

  if (this.user?.id) {

    const payload = {
      user: {
        email: values.email,
      },
    };

    return this._applyService
      .updateOperatorUser(this.user.id, payload)
      .pipe(takeUntil(this._subscription))
      .subscribe(
        (res: BasicResponse) => this.onSuccess(res),
        (err: BasicResponse) => this.onError(err)
      );
  }

  const payload = {
    user: {
      first_name: values.first_name,
      last_name: values.last_name,
      email: values.email,
    },
    roles: [
      values.role
    ]
  };

  return this._applyService
    .createOperator(payload)
    .pipe(takeUntil(this._subscription))
    .subscribe(
      (res: BasicResponse) => this.onSuccess(res),
      (err: BasicResponse) => this.onError(err)
    );
}

感谢您的帮助!

角度 单元测试

评论


答:

0赞 AliF50 11/17/2023 #1

你所拥有的似乎是正确的。我将尝试帮助您调试 s 的问题。使用!.关注评论console.log

onSubmit(): any {
  if (this.userForm.invalid) {
    return;
  }

  this.loading = true;
  const values = this.userForm.value;

  if (this.user?.id) {

    const payload = {
      user: {
        email: values.email,
      },
    };

    return this._applyService
      .updateOperatorUser(this.user.id, payload)
      .pipe(takeUntil(this._subscription))
      .subscribe(
        (res: BasicResponse) => this.onSuccess(res),
        (err: BasicResponse) => this.onError(err)
      );
  }

  const payload = {
    user: {
      first_name: values.first_name,
      last_name: values.last_name,
      email: values.email,
    },
    roles: [
      values.role
    ]
  };
  console.log('!! Here !!'); // add this log and make sure you see it
  return this._applyService
    .createOperator(payload)
    .pipe(takeUntil(this._subscription))
    .subscribe(
      (res: BasicResponse) => this.onSuccess(res),
      (err: BasicResponse) => this.onError(err)
    );
}
fit('should create operator', () => {
    component.data.user = null;
    component.user = null;

    fixture.detectChanges();

    const payload = {
      user: {
        first_name: 'Test',
        last_name: 'Tester', 
        email: '[email protected]',
      },
      roles: [
        [['operator'],],
      ]
    };

    component.userForm.patchValue(payload);

    const response = {
      status: 'success',
      code: 201,
      message: 'Successfully Created a Operator!'
    };
    
    // !! Remove `withArgs` here, it is too specific for nothing !!
    spyOn(ServiceA, 'createOperator').and.returnValue(of(response));
    const submitSpy = spyOn(component, 'onSubmit').and.callThrough();
    const toastSpy = spyOn(toast, 'notifyAction')
      .and
      .callThrough();

    fixture.detectChanges();
    component.onSubmit();

    // !! Add this log
    console.log('!! Making Assertion !!');
    expect(ServiceA.createOperator).toHaveBeenCalled();
    expect(component.onSubmit).toHaveBeenCalled();
    expect(toastSpy).toHaveBeenCalled();
  });

确保您在之前看到 .!! Here !!!! Making Assertion !!

您可能遇到异步问题,也许可以通过 解决。fakeAsync/tick

// !! Add fakeAsync here
fit('should create operator', fakeAsync(() => {
    ...
    component.onSubmit();
    
    tick(); // !! Add tick here to ensure asynchronous activities are done 
            // before carrying on with the test

  }));

您可以研究更多关于 .fakeAsync/tick