Testing NgRx effects with promises – marbles alternative
You can test effects using marbles but unfortunately, they are very complicated.
Instead of marbles, you can test your effects using promises without any trade-offs.
You can view the source code for this project by following this link: GitHub
Writing an example effect to test
Imagine you have written an effect to load tasks but only when they are not loaded yet.
Testing scenarios
Let’s now write testing scenarios. There should be three tests:
should call getTasks method when the state is not LOADED
should not call getTasks method when the state is LOADED
should call getTasks only once even when ToDoActions.loadTasks is called twice
Writing a helper function for test cases
Each scenario will have the same configuration logic so I have created a function to not repeat it each time.
You can do the same with beforeEach function available in Jasmine.
Writing the test to check if getTasks has been called
To check if the method getTasks is called we have to do three things
listen for the result of the effect by using firstValueFrom
emit action to load tasks
check what effect has returned
Writing the test to check if getTasks has not been called
The test will be similar to the previous one, but the difference is the initial state. Here the initial state will be with the status LOADED.
defaultValue will be returned when the subscription (the effect in this case) is completed without emitting any value. That’s so that we can await our promise. Without it, the promise will be rejected.
Writing the test to check if getTasks will not be called twice
In this test, we want to check the case when a user calls the action twice.
We want to handle that case by ignoring the next action.
The test should check if the method getTasks has been called only once even when the action was called twice.
This test will fail because the effect does not have protection for this case.
To handle this case we should replace switchMap with exhaustMap in effect implementation.
Do you like the content?
Your support helps me continue my work. Please consider making a donation.
Donations are accepted through PayPal or Stripe. You do not need a account to donate. All major credit cards are
accepted.