Mike de Klerk
Mike de Klerk

Reputation: 12328

How to use NgRx MockStore setState?

When I am in a unit test with a MockStore, and I use setState on the MockStore, it does not seem to work on its own. See the following code. This code works. But it wouldn't without first calling store.setState({});. This feels hacky. Why is that required, or what am I doing wrong?

function setSelectedBook(bookId: string) {
  let state = (store.source as BehaviorSubject<IAppState>).value;
  state = {
    ...state,
  };
  state.library.bookIdSelected = bookId;
  store.setState({});
  store.setState(state);
}

store is defined as let store: MockStore; and provided to the TestBed just like in the docs provideMockStore({ initialState }).

Upvotes: 0

Views: 3547

Answers (1)

Andrei Gătej
Andrei Gătej

Reputation: 11934

I think the problem is that you're directly mutating the state.library object and without the prior store.setState({}), you'd send the same reference of state.library, which can lead to some unexpected results.

For example, if you have selectors created with createSelector and the library is part of the projection function's arguments, you'll get the previously computed result, because the prevArguments.library object has the same reference as currentArguments.library.

setState({}) is like a deeper refresh, as you're sending a completely new reference.

setState(state) is a different reference compared to {}, so every selector's projection function should be re-run.

I think it should work fine without setState({}) if you do:

state = {
  ...state,
  library: {
    ...state.library,
    bookIdSelected: bookId,
  }
};

store.setState(state);

Upvotes: 4

Related Questions