3 Breaking Dependencies with Stubs

This chapter covers

  • Types of Dependencies – Mocks, Stubs & more
  • Reasons to use stubs
  • Functional Injection Techniques
  • Object Oriented Injection Techniques

In the previous chapter, you wrote your first unit test using jest, and we looked more at the possible structure at maintainability of the test itself. The scenario was pretty simple, and more importantly, it was completely self-contained. The password verifier had no reliance on outside modules, and we could focus only on its functionality without worrying about other things that might interfere with it.

We used the first two types of exit points for our examples: Return value exit points, and state-based exit points. In this chapter we’ll talk about the final one – calling a 3rd party.

This chapter will present a new requirement: – having your code rely on time. We’ll look at two different approaches to handling it – refactoring our code, and monkey-patching it without refactoring.

The reliance on outside modules or functions can and will make it harder to write the test, make the test repeatable, and can cause tests to be flaky.

We call those external things that we rely on in our code dependencies.  I’ll define them more thoroughly later in the chapter. These could include things like time, async execution, using the file system, using the network, or it could simply be using something that is very difficult to configure or may be time consuming to execute.

3.1      Types of Dependencies

3.2      Reasons to use stubs

3.3      Generally accepted design approaches to stubbing

3.3.1   Stubbing out time with parameter injection

3.3.2   Dependencies, Injections and Control

3.4      Functional Injection Techniques

3.4.1   Injecting a function

3.4.2    Using Factory Functions

3.4.3    Moving Towards Objects with Constructor Functions

3.5      Object Oriented Injection Techniques

3.5.1   Constructor Injection

3.5.2   Injecting an object instead of a function

3.5.3   Extracting a common interface.

3.6      Summary