簡體   English   中英

Jasmine單元測試 - 無法讀取未定義的屬性管道

[英]Jasmine Unit test - Cannot read property pipe of undefined

我使用的是Angular 6,NgRx 6,RxJS 6。

我有一個看起來像這樣的護衛員 -

import { CanActivate, ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { IAppState } from '../../../app.state';
import { Store } from '@ngrx/store';

import { SetTenant } from './../../../store/config/config.actions';

@Injectable()
export default class TenantGuard implements CanActivate {
  constructor(private store: Store<IAppState>) {}

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    const tenant = route.params['tenant'];

    if (!tenant) {
      return of(false);
    }

    this.store.dispatch(new SetTenant(tenant));
    return of(true);
  }
}

如您所見,我通過this.store.dispatch(new SetTenant(tenant));將我的tenant添加到商店this.store.dispatch(new SetTenant(tenant));

然而,這導致每次用戶訪問基本路線時都會觸發該動作。

為了解決這個問題,我添加了一個檢查以查看tenant是否已填充,如果沒有,則僅觸發操作 -

import { CanActivate, ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable, of, combineLatest } from 'rxjs';
import { IAppState } from '../../../app.state';
import { Store, select } from '@ngrx/store';

import { SetTenant } from './../../../store/config/config.actions';
import { getTenant } from '../../../store/config/config.selectors';
import { map } from 'rxjs/operators';

@Injectable()
export default class TenantGuard implements CanActivate {
  constructor(private store: Store<IAppState>) {}

  canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    const tenantFromRoute: string = route.params['tenant'];

    return this.store.pipe(select(getTenant)).pipe(
      map(tenantFromStore => {
        if (!tenantFromRoute) {
          return false;
        }

        if (!tenantFromStore) {
          this.store.dispatch(new SetTenant(tenantFromRoute));
        }
        return true;
      })
    );
  }
}

然而這已經破壞了我的單元測試,因為我已經引入了額外的邏輯,我現在得到錯誤TypeError: Cannot read property 'pipe' of undefined

我的spec文件看起來像這樣 -

import { TestBed, async } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { Store } from '@ngrx/store';
import { StoreModule } from '@ngrx/store';

import { SetTenant } from './../../../store/config/config.actions';

import TenantGuard from './tenant.guard';

describe('TenantGuard', () => {
  it('should return false if a tenant is not present on the route', async(() => {
    const { tenantGuard, props } = setup({});
    let result: boolean;
    tenantGuard.canActivate(props).subscribe(canActivate => (result = canActivate));
    expect(result).toBeFalsy();
  }));

  it('should return true if a tenant is present on the route', async(() => {
    const { tenantGuard, props } = setup({ tenant: 'main' });
    let result: boolean;
    tenantGuard.canActivate(props).subscribe(canActivate => (result = canActivate));
    expect(result).toBeTruthy();
  }));

  it('should dispatch an action to set the tenant in the store', () => {
    const { store, tenantGuard, props } = setup({ tenant: 'foo' });
    const action = new SetTenant('foo');
    tenantGuard.canActivate(props);

    expect(store.dispatch).toHaveBeenCalledWith(action);
  });

  it('should not dispatch an action to set the tenant in the store if the tenant is missing', () => {
    const { store, tenantGuard, props } = setup({});
    tenantGuard.canActivate(props);

    expect(store.dispatch).not.toHaveBeenCalled();
  });

  const setup = propOverrides => {
    TestBed.configureTestingModule({
      imports: [StoreModule.forRoot({})],
      providers: [
        TenantGuard,
        {
          provide: Store,
          useValue: jasmine.createSpyObj('Store', ['dispatch', 'pipe']),
        },
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    }).compileComponents();

    const props = Object.assign({ params: { tenant: null } }, { params: { ...propOverrides } });

    const tenantGuard = TestBed.get(TenantGuard);
    const store = TestBed.get(Store);

    return { tenantGuard, props, store };
  };
});

我已將pipe添加到我的jasmine.createSpyObj但是我不確定如何進展。

我想圍繞這個進行額外的測試,但是在模擬出在這種情況下應該/將要使用的pipe時遇到了麻煩。

編輯 - 如果我沒有將pipe傳遞給我的jasmine.createSpyObj而是我得到錯誤​​TypeError: this.store.pipe is not a function​​

我有像你一樣的錯誤信息。 我在一個組件中注入了路由器並使用了this.router.events.pipe(...)...我在測試中使用了一個存根路由器。 在routerStub看起來像這樣之前:

routerStub = {
        navigate: (commands: any[]) => { Promise.resolve(true); },
};

所以你可以看到,在我需要組件中路由器的導航方法之前,我在存根中定義了它。 現在我需要events屬性,它返回一個observable,而不是.pipe。 我在routerStub上添加了以下內容,它為我修復了它:

routerStub = {
        navigate: (commands: any[]) => { Promise.resolve(true); },
        events: of(new Scroll(new NavigationEnd(0, 'dummyUrl', 'dummyUrl'), [0, 0], 'dummyString'))
};

在我的情況下,我需要一個Scroll事件來使我的代碼工作,但現在事件在我的存根中定義為Observable,現在管道是已知的。

也許這有助於你......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM