web-dev-qa-db-ja.com

ngrxテスト:キャッチされないTypeError:スローされた未定義のプロパティ 'xxxx'を読み取ることができません

afterEach(()=> {fixture.destroy();});私は現在、ngrxベースのangular 7アプリケーションのテストを作成しようとしています。問題は、テストがエラーで失敗することですUncaught TypeError: Cannot read property 'xxxx' of undefined thrown。テストファイルは次のようになります。

explore-products.component.spec.ts

import { async, ComponentFixture, TestBed } from "@angular/core/testing";

import { ExploreProductsComponent } from "./explore-products.component";
import { provideMockStore, MockStore } from "@ngrx/store/testing";
import { IAppState } from "src/app/store/state/app.state";
import { Store, StoreModule } from "@ngrx/store";
import { appReducers } from "src/app/store/reducers/app.reducer";

describe("ExploreProductsComponent", () => {
  let component: ExploreProductsComponent;
  let fixture: ComponentFixture<ExploreProductsComponent>;
  let store: MockStore<IAppState>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ExploreProductsComponent],
      providers: [provideMockStore()],
      imports: [StoreModule.forRoot(appReducers)]
    });

    store = TestBed.get(Store);
  });

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

  it("should create", () => {
    expect(component).toBeTruthy();
  });
});

should createテストのみがエラーをスローします。 selectorによってエラーがスローされています。つまり、xxxxプロパティが初期化されていませんが、解決方法がわかりません。コンポーネントは次のようになります。

explore-products.component.ts

import { Component, OnInit, OnDestroy } from "@angular/core";
import { IProduct } from "src/app/models/product";
import { environment } from "src/environments/environment";
import { selectProducts } from "../../store/selectors/product";
import { Store, select } from "@ngrx/store";
import { IAppState } from "src/app/store/state/app.state";
import { Subscription } from "rxjs";

@Component({
  selector: "app-explore-products",
  templateUrl: "./explore-products.component.html",
  styleUrls: ["./explore-products.component.css"]
})
export class ExploreProductsComponent implements OnInit, OnDestroy {
  public productsLoading = true;
  public endpoint = environment.apiEndpoint;

  private productsSelector = this.store.pipe(select(selectProducts));

  public products: IProduct[];
  private subscriptionsArr: Subscription[] = [];

  constructor(private store: Store<IAppState>) {}

  ngOnInit() {
    this.subscriptions();
  }
  subscriptions() {
    const subcriberProduct = this.productsSelector.subscribe(products => {
      this.products = products;
      if (this.products !== null) {
        this.toggleLoadingSign(false);
      }
    });
    this.subscriptionsArr.Push(subcriberProduct);
  }
  toggleLoadingSign(toggleOption: boolean) {
    this.productsLoading = toggleOption;
  }
  ngOnDestroy() {
    for (const subscriber of this.subscriptionsArr) {
      subscriber.unsubscribe();
    }
  }
}

他に情報がありましたらお知らせください。

更新

問題はAppStateにあります。状態が初期化されておらず、エラーが発生するため、エラーがスローされます。つまり、state.xxxxは未定義です。エラーがランダムに発生しない場合があります。これを修正する方法がわかりません。

同じ問題が ここ にも記載されています。しかし、解決策はありません

7
Mj1992

このようなものを試すことができます。私がモックストアを作成して使用した方法をご覧ください。コードが更新された場所に1行コメントを追加(************を使用):

import { async, ComponentFixture, TestBed } from "@angular/core/testing";

import { ExploreProductsComponent } from "./explore-products.component";
import { provideMockStore, MockStore } from "@ngrx/store/testing";
import { IAppState } from "src/app/store/state/app.state";
import { Store, StoreModule } from "@ngrx/store";
import { appReducers } from "src/app/store/reducers/app.reducer";

describe("ExploreProductsComponent", () => {
  let component: ExploreProductsComponent;
  let fixture: ComponentFixture<ExploreProductsComponent>;
  //Update the store def.************
  let store: MockStore<any>;

  beforeEach( async(() => { //*****************UPDATE
    TestBed.configureTestingModule({
      declarations: [ExploreProductsComponent],
      providers: [provideMockStore()],
      //Change to imports************
      imports: [StoreModule.forRoot({})]
    }).compileComponents();//*****************UPDATE
    //Removed this
    //store = TestBed.get(Store);************

  }));//*****************UPDATE

  beforeEach(() => {
    fixture = TestBed.createComponent(ExploreProductsComponent);
    //Get store instance************
    store = fixture.debugElement.injector.get(Store);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it("should create", () => {
    //Spy on store actions************
    const spy = spyOn(store, 'dispatch');
   //Test is store is called properly************
   expect(spy).toHaveBeenCalledWith(Your params)
    expect(component).toBeTruthy();
  });
});
0
RV.