Don´t use Singleton Pattern in your unit tests
Tags: testing, cleancode, testdev, tdd
Published: 2021-06-12 14:35:07

## What is Singleton Pattern?
Is a design pattern that restricts the instantiation of a class to a single instance. This is useful when one object is needed to coordinate actions across the system exemple custom spiner and services. Through this design pattern, the singleton class ensures that it´s only instantiate once, and can provide easy access to the single instante.

## Unit Testing
Is a type of software testing where individual units or componentes of a software are tested. Unit tests isolate a section of code and verify its correctness. A unit test may be an individual function, method, procedure, module or object.

## Why do some programmers use singleton in testing?
Some programmers use Singleton in their tests with the intention of using the **DRY (Don´t repeat yourself)** principle by instantiating the classes that will be used in the tests only once.

##So, why don't use design pattern singleton in Unit tests?
Considering that one of the best practices in unit testing is that tests should be independent and in case of any change in one test the others should not be affected, the singleton pattern hinders testability.

Singletons cause implicit dependencies between conceptually independent units of code. This is problematic both because they are hidden and because they introduce unnecessary coupling between units.

As there is no control over creation, a clean instance of the object cannot be used for each test.

##Example

I'm going to use **TypeScript** and **Jasmine** testing framework in this example.

**State.ts Model**
```
export class State {
  id: number;
  status: string;
  static instance:State;

  constructor(args: {id:number,status: string}) {
    this.id = args.id;
    this.status = args.status;
  }

  static getInstance():State{
    if(!State.instance){
      State.instance = new State({id:1995,status:'LOADING'});
    }
    return State.instance;
  }
}
```

**state.spec.ts**
```
import { State } from .....;

describe('State', () => {
  let state:State = State.getInstance();

  it('UT1 - should state id and status be correct', () => {
    expect(state.id).toEqual(1995); // Will always pass
    expect(state.status).toEqual('LOADING'); // Will always pass
    state.status = 'STOP';
  });

  it('UT2 - should state status be LOADING', () => {
    expect(state.status).toEqual('LOADING'); // It will fail whenever UT1 is run first because the state will always change to STOP
  });

});
```

UT1 (Unit Test 1) and UT2 share state of the same instance of a class causing **unnecessary coupling between unit tests**.

To prevent this from happening we need to perform some setup.

These activities are called setup and teardown (for cleaning up) and Jasmine has function we can use to make this easier.

First we need to add this code in **State.ts**
```
static getCleanInstance():State{
    return new State({id:1995,status:'LOADING'});
 }
```

And now we add this code in **state.spec.ts**
In each test we get a new instance of state eliminating the dependency between tests.
```
let state:State;
  beforeEach(() => {
     state = State.getCleanInstance();
  });
```


##Conclusion

Singleton classes do not allow for Test Driven Development (TDD) [The laws of TDD](https://dev.to/bacarpereira/the-laws-of-tdd-1p1c).

Unit testing depends on tests being independent of one another, so the tests can be run in any order and the program can be set to a known state before the execution of every unit test. Once you have introduced singletons with mutable state, this may be hard to achieve. In addition, such globally accessible persistent state makes it harder to reason about the code, especially in a multithreaded environment.

The Singleton pattern solves many of your problems. You know that you only need a single instance. You have a guarantee that this instance is initialized before it’s used. It keeps your design simple by having a global access point, but don’t use in your unit tests.

Cheers ✌️,
Bc.