Я бы забыл о заглушках здесь. Заглушки / макеты предназначены для того, когда вы хотите имитировать поведение зависимости. Вы бы заглушили свой SomeClass, если бы имели SomeClassClient, который вы хотите протестировать, и он использовал SomeClass:
public class Foo
{
public virtual int GetFoosInt()
{
return 12;
}
}
public class FooClient
{
private Foo _foo;
public FooClient(Foo foo)
{
_foo = foo;
}
public int AddOneToFoosInt()
{
return _foo.GetFoosInt() + 1;
}
}
В этом примере при тестировании FooClient вы хотите проверить, чтобы он возвращал на единицу больше, чем «GetFoosInt ()». На самом деле вам все равно, что такое FoosInt для тестирования FooClient. Итак, вы создаете заглушку Foo, в которой вы можете настроить GetFoosInt, чтобы он возвращал все, что вы хотите.
В вашем случае, тестируя защищенного виртуального участника, я бы сказал:
[TestClass]
public class SomeClassTest
{
private class DummySomeClass : SomeClass
{
public bool IsHappyWrapper(string mood)
{
return IsHappy(mood);
}
}
[TestMethod]
public void SomeTest()
{
var myClass = new DummySomeClass();
Assert.IsTrue(myClass.IsHappyWrapper("Happy"));
}
}
Это дает вам «прямой» доступ к защищенной виртуальной машине для проверки поведения по умолчанию. Единственное предостережение: если вы начнете определять абстрактные элементы и добавлять их в SomeClass в целом, вам придется добавить их и к этому фиктивному наследнику, добавляя к издержкам на обслуживание тестирования.
Пурист во мне говорит, что вы должны оставлять защищенных членов в покое и проверять их только через общедоступный интерфейс. Но это может или не может быть практичным в вашей ситуации, и я не вижу никакого вреда в этом подходе.