Вы снижаете тестируемость вашего класса TableInfo, не внедряя MapInfoWrapper в сам класс. Используете ли вы глобальный кеш этих классов MapInfoWrapper, зависит от класса - вам нужно решить, нужно ли это или нет, но это улучшит ваш дизайн, чтобы передать оболочку в TableInfo и использовать ее там, вместо прямой ссылки на глобальную копию внутри методов TableInfo. Делайте это в сочетании с определением интерфейса (т. Е. «Рефакторинг для интерфейсов»).
Я бы также сделал ленивую реализацию в получателе (ях) Publics, чтобы убедиться, что объект доступен, если он еще не был создан, вместо того, чтобы устанавливать его в конструкторе MapInfoWrapper.
public class TableInfo
{
private IMapinfoWrapper wrapper;
public TableInfo() : this(null) {}
public TableInfo( IMapinfoWrapper wrapper )
{
// use from cache if not supplied, could create new here
this.wrapper = wrapper ?? Publics.InternalMapInfo;
}
public string Name {
get { return wrapper.Eval("String comman to get the name"); }
set { wrapper.Do("String command to set the name"); }
}
}
public interface IMapinfoWrapper
{
void Do( string cmd );
void Eval( string cmd );
}
public class MapinfoWrapper
{
public MapinfoWrapper()
{
}
public void Do(string cmd)
{
//Call COM do command
}
public string Eval(string cmd)
{
//Return value from COM eval command
}
}
internal static class Publics
{
private static MapinfoWrapper _internalwrapper;
internal static MapinfoWrapper InternalMapinfo
{
get
{
if (_internalwrapper == null)
{
_internalwrapper = new MapinfoWrapper();
}
return _internalwrapper;
}
}
}
Теперь, когда вы тестируете методы TableInfo, вы можете легко смоделировать MapInfoWrapper, предоставив конструктору вашу собственную реализацию. Ex (при условии, что рука имитирует):
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void TestTableInfoName()
{
IMapinfoWrapper mockWrapper = new MockMapinfoWrapper();
mockWrapper.ThrowDoException(typeof(ApplicationException));
TableInfo info = new TableInfo( mockWrapper );
info.Do( "invalid command" );
}