I’m working on a legacy project that has heavy use of Singletons. While most of them would be better implemented otherwise, for now the goal is to get them under test. As such, I have the following structure.
public class SomeSingleton
{
private Dependency someDependency;
public static readonly SomeSingleton Instance = new SomeSingleton();
static SomeSingleton() {}
private SomeSingleton()
{
someDependency = new Dependency();
}
}
So, to make it testable without losing the ‘Singelton’ness’, I’ve tried to add a protected constructor that takes the dependency as a parameter to call from an inheriting class that I can run tests through. I realize that making it open for inheritance is breaking the Singleton pattern as well, but it is only used by the test framework and not done, by convention, in the production code.
Like so:
public class SomeSingleton
{
private Dependency someDependency;
public static readonly SomeSingleton Instance = new SomeSingleton();
static SomeSingleton() {}
private SomeSingleton() : this(new Dependency()) {}
protected SomeSingleton(Dependency someDependency)
{
this.someDependency = someDependency;
}
}
public class SomeSingletonTestImplementation : SomeSingleton
{
public SomeSingletonTestImplementation (Dependency someDependency)
: base (someDependency) {}
}
Finally, after the setup, the question:
With this implementation, I expected just the protected constructor in the original Singleton to be called from the inheritor. However, when I debug, the constructor in the inheritor is called, but then, instead of stepping into the protected constructor, the private constructor is called, and then the protected constructor.
Is there any way that the private constructor won’t be called? Also, if anyone has a brief explanation of why it happens the way it does, that’d be great.
Thanks!
Thanks to the answers that pointed me in the right direction. The solution that I came to ended up being the following, which is probably truer to a typical Singleton implementation anyway.
Instead of having a public variable, I turned it into a static property that lazily evaluates the Singleton. That way, the private constructor is only called when the actual Instance property is called, which never happens from the test code, but always from the production code. Then I can happily insert mock dependencies via the protected constructor and test all the public methods via the inheriting class.