chapter six

6 Unit Testing Async Code

 

This chapter covers

  • Async done() and awaits
  • Integration & Unit Test Levels for Async
  • Extract Entry Point Pattern
  • Extract Adapter Pattern
  • Stubbing, Advancing & Resetting Timers
  • Observables, Unit and Marble Testing

When we’re dealing with regular synchronous code, waiting for actions to finish is implicit. We don’t worry about it and we don’t really think about it too much.

When dealing with asynchronous code, waiting for actions to finish becomes an explicit activity which is under our control. A-synchronicity makes code, and also the tests for that code, potentially more tricky because we have to be explicit about waiting for actions to complete.

Let’s start with a simple fetching example to show the issue.

6.1      Dealing with Async Data Fetching

Let’s say we have some a module that checks whether our website at example.com is alive. It does this by fetching the context form the main url and checking for a specific word: “illustrative” to determine if the website is up. In the code below I’ve provided two different very simplistic implementations of this functionality.

The first is with a callback mechanism, and the second is with an async-await mechanism.

Here’s a visual diagram of their entry and exit points for our purposes. Note that the callback arrow is pointed differently to show make it more obvious that it’s a different type of exit point:

Figure : 6.1: IsWebsiteAlive callback vs async/await version

6.1.1   An initial attempt with an integration test

6.1.2   Waiting for the act

6.1.3   Integration testing async-await

6.1.4   Challenges with integration tests

6.2      Making our code unit test friendly

6.2.1   Extracting a Logical Unit of Work

6.2.2   Applying “Extract Entry Point” with Callbacks

6.2.3   Extract Entry Point with Await

6.3      Extract Adapter Pattern

6.3.1   Modular Adapter

6.3.2   Functional Adapter

6.3.3   Object Oriented Interface Based Adapter

6.4      Dealing with Timers

6.4.1   Stubbing timers out with Monkey Patching

6.4.2   Faking setTimeout with jest

6.5      Dealing with Common Events

6.5.1   Dealing with event emitters

6.5.2   Dealing with Click events

6.6      Bringing in dom-testing-library

6.7      Summary