Home > database >  TypeError: Cannot read properties of undefined (reading 'id') angular unit test
TypeError: Cannot read properties of undefined (reading 'id') angular unit test

Time:10-27

I am trying to update item, I wrote a function which gets the items from the store and update with new item based on user's selection with this.name and this.price but the same item.id that is intended for update.

   public updateItemData(){
    return this.store.select(itemSelector).subscribe(item => {
        this.updatedItem = {
            id: item.id,
            name: this.name,
            price: this.price
        }
    })
    }

This works perfectly without any issue but in a unit test.

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

It marked green but with displayed error.

TypeError: Cannot read properties of undefined (reading 'id')

When I ran the project, I didn't get any error concerning the "undefined property" or whatever. I started writing the test

Please help to resolve this. I will appreciate.

CodePudding user response:

Add a spyOn for the store service select. Either inside test or beforeEach

spyOn(store, 'select').and.returnValue(YOUR_VALUE);

make sure to declare store and asiign value inside beforeEach

let store: Store;
store = TestBed.inject(Store); // inside beforeEach

CodePudding user response:

You could use the provideMockStore provided from ngrx like this:

yourcomponent.component.spec.ts

import { provideMockStore } from '@ngrx/store/testing';

describe('...', () => {
 ...  
 ...
 const myMockItemSelectorValue = {...};

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [...],
      imports: [...],
      providers: [
       { 
         initialState: { items: {...}, users: {...} }, // an initial mock Store
         selectors: [{ selector: itemSelector, value: myMockItemSelectorValue }]
       }
      ]
    })
  })
});

Or create a mock of the store using jasmine like the following:

const mockStore = jasmine.createSpyObj<Store>('Store', ['select']);


beforeEach(() => mockStore.select.and.retunValue(of(TheDesiredMockValue))

beforeEach(() => {
  TestBed.configureTestingModule({
     providers: [{ provide: Store, useValue: mockStore }]
  })
})

Personally, I prefer the first option since I can specify multiple selectors with the respective mock values with an initial mock state.

CodePudding user response:

All I had to do is to

  if(this.item === undefined) 
        {
            return
        }

So in my component.ts

  public updateItemData(){
    return this.store.select(itemSelector).subscribe(item => {
     if(this.item === undefined) 
        {
            return
        }
        this.updatedItem = {
            id: item.id,
            name: this.name,
            price: this.price
        }
    })
    }

All error disappeared and mocking using overrideSelector was successful.

  • Related