【问题标题】:Error: Expected spy create to have been called错误:预期的间谍创建已被调用
【发布时间】:2023-04-06 10:47:01
【问题描述】:

我正在为 Component with async service 编写 Angular 7 的单元测试用例并收到此错误:

错误:预期的 spy create 已被调用一次。它被称为 0 次。

这是我的组件:

export class RegistrationComponent implements OnInit {
    
   submitRegistrationForm() {
        if (this.profileForm.invalid) {
          this.validateAllFields(this.profileForm);
        } else {
          // send a http request to save this data
          this.guestUserService.create(this.profileForm.value).subscribe(
            result => {
              if (result) {
                console.log('result', result);
                this.router.navigate(['/login']);
              }
            },
            error => {
              console.log('error', error);
            });
        }
  }

单元测试用例:

  describe('RegistrationComponent', () => {
      let component: RegistrationComponent;
      let fixture: ComponentFixture<RegistrationComponent>;
      let myService;
      let mySpy;
    
      beforeEach(async(() => {
    
        TestBed.configureTestingModule({
          declarations: [RegistrationComponent],
          imports: [ ],
          providers: [
            { provide: GuestUserService, useValue: new MyServiceStub() }]
        })
          .compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(RegistrationComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });

 it('should submit Registration Form', async(inject([Router], (router) => {
    myService = TestBed.get(GuestUserService);
    mySpy = spyOn(myService, 'create');
    spyOn(router, 'navigate');
    spyOn(component, 'submitRegistrationForm');


component.profileForm.controls['firstName'].setValue('Arjun');
    component.profileForm.controls['lastName'].setValue('Singh');
    component.profileForm.controls['password'].setValue('12345678');
    component.profileForm.controls['confirmPassword'].setValue('12345678');
    component.submitRegistrationForm();

    expect(component.profileForm.invalid).toBe(false);

    expect(component.submitRegistrationForm).toHaveBeenCalled();

    expect(myService).toBeDefined();
    expect(mySpy).toBeDefined();
    expect(mySpy).toHaveBeenCalledTimes(1); // Getting error is this
    expect(router.navigate).toHaveBeenCalled();
  })
  ));

我试图在 beforeEach 中移动间谍减速,但仍然给出相同的错误。

如何解决这个错误?

谢谢!

【问题讨论】:

  • 你能改变你的行显示这样的错误并尝试 - expect(myService .create).toHaveBeenCalledTimes(1);
  • 您需要在调用被测方法之后和预期之前调用detectChanges 或调用done(注入后)。
  • 你好@user2216584,我试过这个expect(myService .create).toHaveBeenCalledTimes(1);但仍然得到同样的错误:(
  • 嗨@TheHeadRush,fixture.detectChanges();效果不佳。
  • @ArjunSingh 您的组件的 else 条件似乎没有被执行。将console.log 放入ifelse 条件中,看看会得到什么日志。通过查看您的测试用例,您的组件的 this.profileForm 似乎无效,因此您的 submitRegistrationForm 方法的 else 条件没有被执行。你确定 submitRegistrationForm 的 else 条件被调用了吗?放置日志并检查。

标签: javascript angular typescript unit-testing karma-jasmine


【解决方案1】:

预期的 spy create 已被调用不是错误,而是测试失败。

这是因为您没有使用 callThrough();在你的 spyOn 上。

 it('should submit Registration Form', async(inject([Router], (router) => {

    myService = TestBed.get(GuestUserService);
    mySpy = spyOn(myService, 'create').and.callThrough(); //callThrough()

    spyOn(router, 'navigate');

    spyOn(component, 'submitRegistrationForm').and.callThrough(); //callThrough()


    component.submitRegistrationForm();

    expect(component.profileForm.invalid).toBe(false);

    expect(component.submitRegistrationForm).toHaveBeenCalled();

    expect(myService).toBeDefined();
    expect(mySpy).toBeDefined();
    expect(mySpy).toHaveBeenCalledTimes(1); 
    expect(router.navigate).toHaveBeenCalled();
  })
  ));

【讨论】:

  • 谢谢你。它与表单控件配合得很好。
【解决方案2】:

spyOn 将帮助您设置函数在测试中被调用时的反应方式。基本上这是 Jasmines 创建模拟的方式。

在您的情况下,您已经定义了在调用服务函数时测试应该做什么,即callThrough。问题是您还需要对服务功能(或调用您的服务方法的范围功能)采取行动,以触发spyOn,这将是callThrough

it('load snapshot',function(){

  //setup
  spyOn(MyService, 'loadSomething').and.callThrough(); //statement 2

  //act

  //either call the scope function which uses the service 
  //$scope.yourServiceCallFunction();

  //or call the service function directly
  MyService.loadSomething(1); //this will callThrough

});

这是一个简单的测试,我们将模拟 spyOn 对字符串的响应

it('test loadSomething',function(){

  //setup
  spyOn(MyService, 'loadSomething').and.returnValue('Mocked');

  //act
  var val = MyService.loadSomething(1);

  //check
  expect(val).toEqual('Mocked');
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    相关资源
    最近更新 更多