С RhinoMocks у вас должен быть интерфейс. Если вам действительно нужно высмеивать это, вам придется немного обмануть, поместив синглтон в другой класс, который создает интерфейс. Этот интерфейс должен быть в основном точной копией всех открытых членов стороннего синглтонного типа.
Концепция похожа на Duck Typing , но, поскольку CLR не поддерживает Duck Typing, вы должны использовать прокси-класс.
Вот пример:
public interface ISingleton
{
void SomePublicMethod();
Int32 SomePublicProperty{ get; set; }
}
public class SingletonProxy: ISingleton
{
private ThirdPartySingleton _singleton = StaticType.GetSingleton(); // ???
public void SomePublicMethod()
{
_singleton.SomePublicMethod();
}
public Int32 SomePublicProperty
{
get{ return _singleton.SomePublicProperty; }
set{ _singleton.SomePublicProperty = value; }
}
}
Так что теперь в любом типе, в котором вы используете это, вы можете передать это как служебную зависимость следующим образом:
public class TypeThatUsesSingleton
{
private ISingleton _singleton;
public TypeThatUsesSingleton([HopefullySomeDependencyInjectionAttributeHere] ISingleton singleton)
{
_singleton = singleton;
}
public void DoStuff()
{
_singleton.SomePublicMethod();
}
}
Теперь вы должны быть в состоянии счастливо смоделировать класс в своем тесте и передать его в качестве зависимости для продолжения ваших модульных тестов:
[Test]
public void ShouldAssertSomeBehavior()
{
var repo = new MockRepository();
var singleton = repo.DynamicMock<ISingleton>();
var sut = new TypeThatUsesSingleton(singleton);
using(repo.Record())
{
singleton.SomePublicMethod();
}
using(repo.Playback())
{
sut.DoStuff();
}
}
Вуаля! Счастливо издевались над синглтоном без головной боли (хорошо, так немного головной боли). Вы, вероятно, думаете, что весь класс Proxy станет проблемой, но, к счастью, некоторые хорошие люди сделали это немного легче. Все, что я упоминал ранее в Duck Typing ... есть библиотека с открытым исходным кодом, которая сгенерирует ваш прокси-класс для вас во время выполнения.
Duck Typing .Net