Если класс напрямую зависит от Application.Current
, вы не можете его протестировать.Но похоже, что вы уже на пути к зависимости от абстракции.
Предположим, вам нужно сделать три вещи:
- Получить свойство
- Установить свойство
- Сохранить все свойства
Вы можете определить абстракцию, которая представляет такое поведение:
public interface IApplicationProperties
{
object GetProperty(string key);
void SetProperty(string key, object value);
Task SavePropertiesAsync();
}
Ваша реализация по умолчанию может выглядеть следующим образом(хотя есть много возможностей для улучшения.)
public class ApplicationProperties : IApplicationProperties
{
private readonly Application _application;
public ApplicationProperties(Application application)
{
_application = application;
}
public object GetProperty(string key)
{
// or whatever behavior you want when the key is missing
return _application.Properties.TryGetValue(key, out object result) ? result : null;
}
public void SetProperty(string key, object value)
{
_application.Properties[key] = value;
}
public async Task SavePropertiesAsync()
{
await _application.SavePropertiesAsync();
}
}
Этот класс может зависеть от Application.Current
, или вы можете добавить Application
в него.
Это может быть лучшепроверка типа и, возможно, ограничение / определение того, какие настройки можно прочитать и установить.Но он позволяет вам получить доступ к поведению Application
через абстракцию, одновременно высмеивая абстракцию для модульных тестов.Вы можете использовать Moq
или просто написать простой тестовый двойник для использования в тестах.
Вот твик к подходу, который включает двойной тест:
// base class
public abstract class ApplicationPropertiesBase : IApplicationProperties
{
protected abstract IDictionary<string, object> Properties { get; }
public object GetProperty(string key)
{
return Properties.TryGetValue(key, out object result) ? result : null;
}
public void SetProperty(string key, object value)
{
Properties[key] = value;
}
public abstract Task SavePropertiesAsync();
}
// inject this
public class ApplicationProperties : ApplicationPropertiesBase
{
private readonly Application _application;
public ApplicationProperties(Application application)
{
_application = application;
}
protected override IDictionary<string, object> Properties => _application.Properties;
public override async Task SavePropertiesAsync()
{
await _application.SavePropertiesAsync();
}
}
// use for tests
public class ApplicationPropertiesTestDouble : ApplicationPropertiesBase
{
private readonly IDictionary<string, object> properties =
new Dictionary<string, object>();
protected override IDictionary<string, object> Properties => properties;
public override async Task SavePropertiesAsync()
{ }
}