1

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.

3 Answers 3

1

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
Sign up to request clarification or add additional context in comments.

3 Comments

This is exactly what I did.
Return observable select').and.returnValue(of(YOUR_VALUE))
Yes, I did but I think I didn't check if there is this.item === undefined.
1

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.

Comments

0

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.

2 Comments

What is "this.item"? Looks like you're mixing class members and locale variables here. And beyond that, an emty return is pretty bad style. Make the condition if (item !== undefined) instead, then you can save yourself this pointless return. Check your test, if it really tests something.
Thanks... i have adjusted it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.