Testing against alternative flows

Let’s imagine ngrx/store user slice of a very simple forum like application.

Store and user component

Notice the conditional presentation of user’s registration date in this dead
simple user-component. If the user is registered on the forum than their registration date
is fetched on a selection from the store. Otherwise, no registration date is fetched and a
static fallback text is used. The component under test is presented on code snippets below.

The conditional logic in the template file is what we may want to test.

a) write your own store mock

One of the possible approaches to testing store dependent component would be to use self-written store mock object.

The test above is perfectly fine, but it covers only the first case (registration date is present in store).
With this approach to test the second case, we need to create the component once again but this time provide
another version of mock that actually returns no registration date. This will probably cause repetition of the
whole beforeEach section which is not optimal.

b) use jasmine’s spy object

Another solution would be to use jasmine’s spy on the select method, provide it when the test module is being
configured and then control return value from the test itself.

Using jasmine spy seems to be the more flexible solution and lets us cover both test cases without
necessary hassle and code repetition.

Testing against multiple selections

Store slices and thread component

The complexity here comes from double selecting different store slices.
The component under test is presented on code snippets below.

a) write your own store mock

Below I present one of the possible implementations, of self-written store mock.
There are of course other ways to do the same.

No matter how it is implemented this approach seems to be far from perfect and for
more complex components it may get tricky. The conditional logic in mock grows with
each new store slice selection. Test suite built around such an approach is hardly extendable.

b) use jasmine’s spy object

Let’s see jasmine’s spies in action. Spy is created and injected on configure phase and return
values are controlled from the single test.

Again, using jasmine’s spy makes the code cleaner and fancier. Since the assertion strongly
relies on return values it makes sense to have it in test code, not in the test suite setup phase.
The main drawback here is the tight coupling between the test case and the sequence of calls in the thread component.
Whenever component calls sequence changes test suite needs to follow.

c) use jasmine’s withArgs() method

This is my personal favorite as there is no invocation dependency here.
I like withArgs() that much, that I’ve created PR to add this missing
cool feature to typescript typings. Describing jasmine’s spy behavior with
the use of withArgs() makes it super readable as we clearly see return values
in different invocations from a single test.

Note: Jasmine’s withArgs() spy method is available from version 3.0, however,
it is not yet easily available for typescript users due to lack of types definitions.
We will be able to use with newest jasmine and jasmine/types versions as soon as the
pull request gets merged to master.


From all methods presented above the one powered by jasmine’s spies and withArgs() seems to be the most readable and is
surely my personal choice, especially in cases where component relies on multiple selections from a store.

Source code: https://github.com/piorot/ngrx-store-testing