Одна проблема с синглетами, реализованными как статические экземпляры, заключается в том, что они затрудняют тестирование и макетирование.
Смотрите этот сценарий:
public void BusinessLogicMethod()
{
var initialValue = MySingleton.Instance.GetInitialValue();
var processedValue = initialValue + specialSomething + businessLogic;
MySingleton.Instance.SaveProcessedValue(processedValue);
}
Теперь, допустим, я хочу написать юнит-тест для этого метода.В идеале я хочу написать тест, который определяет ввод и вывод и тестирует только бизнес-логику.Но со статическим синглтоном реализация метода привязана к реализации синглтона.Могу ли я легко установить InitialValue в начале теста, или это зависит от других факторов / доступа к БД / чего-либо еще?
Однако, если я использую нестатический синглтон в сочетании с некоторым внедрением зависимости или службойШаблон локатора, я могу построить свою функцию следующим образом:
public void BusinessLogicMethod()
{
var singleton = ServiceLocator.Resolve<MySingleton>();
var processedValue = singleton.InitialValue + specialSomething + businessLogic;
singleton.SaveProcessedValue(processedValue);
}
, и мой тест может пойти так, используя смутный синтаксис Moq-подобного:
public void TestBusinessLogic()
{
MySingleton fakeSingleton = new Mock<MySingleton>();
fakeSingleton.Setup(s => s.InitialValue).Returns(5);
// Register the fake in the ServiceLocator
ServiceLocator.Register<MySingleton>(fakeSingleton.Object);
// Run
MyBusinessMethod();
// Assert
fakeSingleton.Verify (s => s.SaveProcessedValue()).Called(Exactly.Once);
}
, не беспокоясь о РЕАЛЬНОМСинглтонная реализация.