业力类型错误“无法读取未定义的属性'订阅'" [英] karma TypeError "Cannot read property 'subscribe' of undefined"

查看:18
本文介绍了业力类型错误“无法读取未定义的属性'订阅'"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在测试具有共享服务的简单组件时,出现以下错误消息,我无法使其工作,我已经尝试了所有方法!

While testing a simple component that has a shared service, the following error message appears, and I cannot manage to make it work, I've tried everything!

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

TypeError: Cannot read property 'subscribe' of undefined

lr.component.ts

export class LrComponent implements OnDestroy {
  currentRouter: string;
  private subscription: Subscription;

  constructor(private lrService: LrService) {
    this.subscription = this.lrService.lrNavigation$.subscribe(
      (currentNav: string) => {
        this.currentRouter = currentNav;
      },
      (error) => {
        console.warn(error);
      }
    );
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
}

lr.service.ts

@Injectable()
export class LrService {
  // Observables for our components to subscribe to.
  lrNavigation$: Observable<string>;

  // Subjects to return data to subscribed components
  private lrNavigationSubject = new Subject<string>();

  constructor() {
    this.lrNavigation$ = this.lrNavigationSubject.asObservable();
  }

  // Triggers subscribed components
  lrNavigate(currentNav: string) {
    this.lrNavigationSubject.next(currentNav);
  }
}

any-random.component.ts

// In another component we send the string that we want the subscribed component (LrComponent) to receieve
this.lrService.lrNavigate('LR');

lr.component.spec.ts

class MockRouter {
  navigate = jasmine.createSpy('navigate');
}

class MockActivatedRoute {
  params = jasmine.createSpy('params');
}

class MockLrService extends LrService {
  lrNavigation$: Observable<string> = new Subject<string>().asObservable();

  constructor() {
    super();
  }

  lrNavigate(currentRouter: string) {
    return Observable.of(['LR']);
  }
}

export function main() {
  describe('LrComponent', () => {
    let fixture: ComponentFixture<LrComponent>;
    let component: LrComponent;
    let lrService: LrService;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          LrComponent,
          LrMappingsComponent,
          LrCategoriesComponent,
        ],
        imports: [
          RouterTestingModule,
          CommonModule,
          LrRoutingModule,
          SharedModule,
          AgGridModule.withComponents(
            [
              CaseSensitiveFilterComponent,
              ButtonComponent,
              ColumnHeaderComponent,
              TypeaheadEditorComponent,
              ButtonGroupComponent
            ]
          )
        ],
        providers: [
          { provide: LrService, useClass: MockLrService },
          { provide: Router, useClass: MockRouter },
          { provide: ActivatedRoute, useClass: MockActivatedRoute },
        ]
      }).compileComponents();
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(LrComponent);
      component = fixture.componentInstance;
      lrService = fixture.debugElement.injector.get(LrService);
    });

    it('should create LrComponent', () => {
      fixture.detectChanges();
      expect(component).toBeDefined();
    });

    it('should have the current router set', async(() => {
      fixture.detectChanges();
      expect(component.currentRouter).toEqual('LR', 'the data should be `LR`');
    }));
  });
}

错误

注意:

如果我使用 ONLY Jasmine,没有 Angular 测试框架的东西,它可以工作.但这不是我想要测试 @Component 的方式.

If I use ONLY Jasmine, with no Angular testing framework stuff, it works. But that's not how I want to test @Component's.

例子:

export function main() {
  describe('LrComponent', () => {
    let fixture: ComponentFixture<LrComponent>;
    let component: LrComponent;
    let lrService: LrService;

    beforeEach(() => {
      lrService = new MockLrService();
      component = new LrComponent(lrService);
    });

    it('should create LrComponent', () => {
      fixture.detectChanges();
      expect(component).toBeDefined();
    });
  });
}

这可行,但不是我想要的.

This works, but is not what I want.

关于如何解决这个问题的任何线索?我真的尝试了很多东西,但都没有奏效......

Any clue on how to solve this issue? I really tried many things and none worked...

推荐答案

好的,我会回答自己,以防有人遇到同样的问题.

Ok, I'll answer myself in case someone faces the same issue.

原来是删除:

{ provide: Router, useClass: MockRouter }

解决了这个问题.我真的不知道为什么.我确信服务中的 Observable 存在一些问题......

Solved the issue. I really don't know why. I was convinced it was some issue with the Observables from the service...

这些依赖项出现在这里是因为:

These dependencies were here because of this:

it('should be able to navigate through tabs',
      fakeAsync((inject([Router, Location], (router: Router, location: Location) => {
        router.initialNavigation();

        let tabLinks, a1, a2;
        fixture.detectChanges();

        tabLinks = fixture.debugElement.queryAll(By.css('a.mappings'));
        a1 = tabLinks[0];
        a2 = tabLinks[1];


        a1.triggerEventHandler('click', { button: 0 });
        tick();
        expect(location.path()).toEqual('lrMappings');

        a2.nativeElement.click();
        tick();
        expect(location.path()).toEqual('categories');
      }))));

但是,将它们从 providers 中删除并像此处所示那样注入它们就可以了.

But, removing them from providers and injecting them like shown here makes it work.

这篇关于业力类型错误“无法读取未定义的属性'订阅'"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆