Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singletons testing and subclassing

I saw this while using picocontainer. They say you have to avoid singletons. because the Singleton pattern makes it almost impossible for the class (and possibly all other classes which depend on it) to be testable. It's very hard to subclass, or to create a mock object for a Singleton class.

But if you absolutely need it , Is there a workaround for the testing and subclassing issue ?

like image 690
Mouna Cheikhna Avatar asked Aug 04 '11 13:08

Mouna Cheikhna


People also ask

What is the best way to subclass singletons?

A singleton class has a private constructor which is not accessible to any other class inside the same package or outside. Hence it cannot be sub classed from any other class.

What is a singleton test?

The Singleton pattern is a useful pattern in Android development, and Java development at large. The Singleton pattern is defined as follows: In software engineering, the singleton pattern is a design pattern that restricts the instantiation of a class to one object.

Can we create subclass of Singleton class?

Subclassing a Singleton class may be tricky, since a subclass object cannot be created unless the superclass object has not yet been created. You may want to extend the Singleton class to allow not just a single instance, but some small fixed maximum number of instances.

How do singleton affect testing?

Singleton object is pretty hard to fake in tests and thus we can consider it as untestable code. Singleton keeps state for the lifetime of the application. So we cannot run several tests using this object at the same time, they will conflict with each other.


2 Answers

What makes it hard to test singletons is the code enforcing their singleton-ness (meaning the public static MySingleton getInstance() {...} boilerplate). Using an inversion-of-control container, like Picocontainer or Guice or Spring, removes that concern from the object, so now:

  • It can be instantiated and have collaborators plugged into it in tests without a problem.

  • The code calling a singleton doesn't have to know what class it is looking up (which it would need to know if it had to call a static method).

I interpret the advice on picocontainer's website as being similar to this. What they are telling you is, let our container manage the scope of your components for you, don't hard-wire the scope-enforcing code into them.

like image 176
Nathan Hughes Avatar answered Nov 03 '22 05:11

Nathan Hughes


If you must have singletons:

  1. Have an interface describing each singleton
  2. Access your singletons from a global/singleton ServiceLocator
  3. Switch the instances registered in the ServiceLocator during testing

Example:

interface IBankApi
{
   public void MakeDeposity(int accountNumber, int dollarAmount);
   // ...
}

public class RealBankApi : IBankApi { ... }

// startup code
serviceLocator.Register<IBankApi>(new RealBankApi());

// code using the API
serviceLocator.Resolve<IBankApi>().MakeDeposit(...);

// test code setup
class FakeBankApi : IBankApi { ... }
serviceLocator.Register<IBankApi>(new FakeBankApi());
like image 1
orip Avatar answered Nov 03 '22 07:11

orip