Test logics by running them through middleware in mock store #2026
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Instead of exercising logics by calling the
process()
method directly, creates amakeTestLogic
test helper that sets up a mock store with theredux-logic
middleware configured with only the logic under test.This change was initially motivated by an observation that several of our logic tests were relying on the implementation detail that our
process()
methods tend to be async methods that settle when the logic is done; however, in those cases, what actually matters is thedone()
callback being called.After a first cut that created a test helper that replicated the way
redux-logic
handles different implementations of theprocess()
method, I still didn’t like how much manual testing of Observables and such we had to do for the more advanced logics.So, instead, test logics by running them through
redux-logic
. The test helper abstracts creating the middleware and mock store, so actual tests are still just concerned with the behavior of the logic. The helper returns a promise that resolves when the logic completes, by hooking into the globalmonitor$
observable inredux-logic
. Tests can optionally pass anafterDispatch
function to trigger behaviors that the logic waits for.It’s reasonable to question whether this approach really qualifies as unit testing—after all, we’re creating an entire Redux store to test behavior here—but I think it still fully qualifies. We’re still testing one particular software component (a logic) in isolation from the rest of our application; the question is just how to test that component most effectively. In the case of
redux-logic
, the behavior of the logic is the result of a fairly complex interaction between our code and library code; so testing it in the context of the library is the best way to ensure that it’s working the way we want.As it happens, switching to the helper caught a bug in one of the logic’s implementations, which is fixed here as well.