Don´t use Singleton Pattern in your unit tests

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 thi…


This content originally appeared on DEV Community and was authored by Abú-Bakr Pereira Kebé

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 codde 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.

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.


This content originally appeared on DEV Community and was authored by Abú-Bakr Pereira Kebé


Print Share Comment Cite Upload Translate Updates
APA

Abú-Bakr Pereira Kebé | Sciencx (2021-06-12T14:35:07+00:00) Don´t use Singleton Pattern in your unit tests. Retrieved from https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/

MLA
" » Don´t use Singleton Pattern in your unit tests." Abú-Bakr Pereira Kebé | Sciencx - Saturday June 12, 2021, https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/
HARVARD
Abú-Bakr Pereira Kebé | Sciencx Saturday June 12, 2021 » Don´t use Singleton Pattern in your unit tests., viewed ,<https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/>
VANCOUVER
Abú-Bakr Pereira Kebé | Sciencx - » Don´t use Singleton Pattern in your unit tests. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/
CHICAGO
" » Don´t use Singleton Pattern in your unit tests." Abú-Bakr Pereira Kebé | Sciencx - Accessed . https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/
IEEE
" » Don´t use Singleton Pattern in your unit tests." Abú-Bakr Pereira Kebé | Sciencx [Online]. Available: https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/. [Accessed: ]
rf:citation
» Don´t use Singleton Pattern in your unit tests | Abú-Bakr Pereira Kebé | Sciencx | https://www.scien.cx/2021/06/12/dont-use-singleton-pattern-in-your-unit-tests/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.