afterEach(() => {
fixture.destroy();
});I am currently trying to write tests for my ngrx based angular 7 application. The problem is that my test fails with the error Uncaught TypeError: Cannot read property 'xxxx' of undefined thrown
. Here's how my test file looks like.
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();
});
});
The only should create
test is throwing the error. The error is being throwing by the selector
somehow, which means the xxxx
property is not initialized but I am not sure how to resolve it. Here's what my component looks like.
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();
}
}
}
Please let me know if I can provide any other information.
Update
The problem is with AppState
. The error is thrown since the state is not initialized which causes the error to occur i.e state.xxxx
is undefined. The error sometimes randomly doesn't occur. I am not sure how to fix this.
The same problem is also mentioned here. But no solution
For me adding this line of code afterEach(() => { fixture.destroy(); });
in all my spec files injecting provideMockStore()
fixed this issue intermittently triggering.
describe('Component', () => {
let component: Component;
let fixture: ComponentFixture<Component>;
beforeEach(async(() => {
const state = { featureKey: { property: value } }; // The state of your feature snippet
TestBed.configureTestingModule({
providers: [
provideMockStore({ initialState: state }),
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(Component);
component = fixture.componentInstance;
fixture.detectChanges();
});
afterEach(() => { fixture.destroy(); });
it('should create', () => {
expect(component).toBeTruthy();
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With