【问题标题】:TypeError: Cannot read property 'subscribe' of undefined using spyOnTypeError:无法使用 spyOn 读取未定义的属性“订阅”
【发布时间】:2020-05-26 22:37:42
【问题描述】:

我期望在我的Angular 应用程序的测试中未定义一个数组。为了做到这一点,我的测试需要首先调用我测试过的组件的一个函数。在该函数中,它订阅服务的函数。

这是我的测试课。包括服务和模拟服务的必要设置以及测试本身。测试包括我已经尝试过的注释行。

let service: Service;
const mockService = new MockService();
mockService.getById = of([]);

beforeEach(async(() => {
    return TestBed.configureTestingModule({
      declarations: [leaving out for now],
      imports: [leaving out for now],
      providers: [
        {
          provide: Service,
          useValue: mockService 
        }
      ]
    })
      .compileComponents();
  }));

beforeEach(() => {
    fixture = TestBed.createComponent(Component);
    component = fixture.componentInstance;

    service = fixture.debugElement.injector.get(Service);

    fixture.detectChanges();
  });

describe('describe test', function () {
    it('test', function () {
      //spyOn(mockService, 'getItemsById');
      //spyOn(mockService, 'getItemsById').and.returnValue(of('nothing'));
      //spyOn(service, 'getItemsById');
      //spyOn(mockService, 'getItemsById').and.callThrough();
      //spyOn(service, 'getItemsById').and.callThrough();
      //spyOn(service, 'getItemsById').and.returnValue(of('nothing')); syntax error
      //spyOn(service, 'getItemsById').and.returnValue({ subscribe: () => {} }); syntax error
      //spyOn(mockService, 'getItemsById').and.returnValue({ subscribe: () => {} }); syntax error
      component.getList();

      expect(component.array).toBeUndefined();
    });
  });

我尝试的所有方法仍然导致错误:

TypeError: 无法读取未定义的属性“订阅”

它引用了我订阅服务的getItemsById 函数的组件函数中的行

我的模拟服务:

getById: Observable<any>;

constructor() {}

getItemsById(id: number){
    return this.getById;
  }

订阅原始服务功能的测试组件:

getList(): Model[]{
    let temp: Model[] = [];
    for (let item of this.items){
      let id = item.id;
      this.service.getItemsById(id).subscribe(
        singleIdItem => {
          temp= temp.concat(singleIdItem);
        }
      );
    }
    return temp;
  }

我没有包含我的原始服务,因为它被模拟了,如果需要,请告诉我。我假设解决方案是某种形式的spyOn,但我已经尝试了所有能找到的方法。

使用 Angular 8

【问题讨论】:

  • 您能否尝试在 stackblitz 或 codepen 或类似的方法中重新创建问题?

标签: angular angular8 angular-test spyon


【解决方案1】:

在第一个 beforeEach 之前试试这个:

let service: Service;
const mockService = new MockService();
mockService.getById = of([]);

我正在考虑在第二个beforeEach 中添加mockService.getById = of([]);(现在将其从此处删除,因为它已添加在顶部)为时已晚(没有getById 的服务已经注入@ 的提供者中987654326@).

========================编辑===================

我会像这样使用createSpyObj

let mockService: any;

beforeEach(async(() => {
      // can name service (first argument) to anything you want, but I called in service in this scenario. It is internal for you
    mockService = jasmine.createSpyObj('service', ['getItemsById']);
    TestBed.configureTestingModule({
      declarations: [leaving out for now],
      imports: [leaving out for now],
      providers: [
        {
          provide: Service,
          useValue: mockService 
        }
      ]
    })
      .compileComponents();
  }));

beforeEach(() => {
    fixture = TestBed.createComponent(Component);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

it('should do something', () => {
   mockService.getItemsById.and.returnValue(of([]));
   component.getList();
   // the rest of your assertions.
});

【讨论】:

  • 不幸的是,这不起作用。它会导致相同的错误。我编辑了我的问题以包含此建议。
【解决方案2】:

在我的测试中,我需要从我的服务中返回正确的值

describe('describe test', function () {
    it('test', function () {
      spyOn(service, 'getItemsById').and.returnValue(of([{name: 'name', id: 10, otherId: 12, startTime: 'time', endTime: 'time', description: 'desc', insertTime: 'time', insertUser:'user', updateTime: 'time', updateUser: 'user'}]));

      component.getList();

      expect(component.array.size).toEqual(1);
    });
  });

返回的值是Model[] 类型,如我的服务中的getList 函数中定义的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-13
    • 2020-06-17
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多