Mock your NGRX store, the easy way!

NGRX, is an amazing way to apply the redux pattern in Angular.
Writing tests for this pattern within our Angular applications is also a part of our daily development work. When writing unit tests we want to test small pieces of logic, that way it’s easy to identify bugs in an early stage.

But there is a small (big) problem! As of ngrx version 6 `` is deprecated, the new way is to use `store.pipe(select….`

NGRX 6: is deprecated

So we need to find a way to mock the select so that we are able to provide it 
in a proper way to our test component. We only want to test the component and not the functionality behind it, after all we are writing UNIT test, This means we just want to test a particular part of the functionality, not the complete project! This allows us to test a small part, so we can discover fast how to solve these problems.

For the demo application we create a random quote display.

Display the quote on the screen

We want to test the QuoteComponent to check if everything is displayed correctly on the screen. Below is an example of how we would write a unit test
when we would use

But this no longer a valid approach since we need to do it like this

A solution is needed !!!

We will mock the complete store, since we want decide ourselves what’s in the store.

If we want to use the ngrx store we need a few key concepts:

  • Actions describe unique events that are dispatched from components and services.
  • State changes are handled by pure functions called reducers that take the current state and the latest action to compute a new state.
  • Selectors are pure functions used to select, derive and compose pieces of state.
  • State accessed with the Store, an observable of state and an observer of actions.
No longer to need this complete implementation on your project. I created a NPM package for it!

Step 1: Create a mockActions

As we want to mock our complete store, we want to have a mock action to fill the store with data!

Step 2: Create a mockReducer

From the moment the store retrieves a mocked action, it will be saved to the store. In fact we will store every action.

No complex logic is added, as we want to decide in our test how the data looks. Don’t forget we only want to test a small piece of our code!

Step 3: Create a MockStoreModule

Of course we want to use the reducer for the right feature. And we want to avoid to much boilerplate code! So let’s create a shared module!

We want to achieve something like

With the forRoot method we can decide which feature we want to mock in our store. Also the initial state we can decide ourselves!

Let’s take a look at the MockStoreModule:

the forRoot(featureName: string, initialState: unknown) is required to make the featureName and initial value of the state! This function will call a factory method before the test will start, which will initialise the mock reducer as described above. ReduceManager is provided by default by @ngrx/store. The reduce manager provide some methods to add and remove features dynamically. It is also used internal in the ngrx store.

addFeature(feature: StoreFeature<any, any>): void;
addFeatures(features: StoreFeature<any, any>[]): void;
removeFeature(feature: StoreFeature<any, any>): void;
removeFeatures(features: StoreFeature<any, any>[]): void;
addReducer(key: string, reducer: ActionReducer<any, any>): void;
addReducers(reducers: {
[key: string]: ActionReducer<any, any>;
}): void;
removeReducer(featureKey: string): void;
removeReducers(featureKeys: string[]): void;

If we look at the functions, we can also take some benefit out of it when writing unit tests. So let’s create our initReducer function

Step 4: Use the existing selectors

Selectors we will not mock. This part would be too difficult and it doesn’t add any added value in most cases.

If we take a look at our quote selectors, it only returns a part of our state.

So if we want to add a quote to the mocked store

We can apply the selectors in an easy way to our store.

No longer to need this complete implementation on your project. I created a NPM package for it!

Step 5: Apply the mock store on your tests

If we take a look at our complete test

The complete code can be found here

So happy testing with the store

Next article will be how to mock your store with marble testing!

Special thanks to Maarten Tibau

More about me!