Как я могу проверить методы, содержащие Application.Current - PullRequest
1 голос
/ 01 июля 2019

Есть несколько методов, которые имеют методы Application.Current.Properties и Application.Current.SavePropertiesAsync.

Итак, как мне проверить методы, в которых есть эти два?Я застрял после попытки использовать контейнер Unity для них, но он работает только для свойств, а не SavePropertiesAsync.

Как я могу это реализовать?

Я реализовал это как:

public interface IAppProperties { IDictionary<string, object> Properties { get; set; } }

public class AppProperty:IAppProperties
{
    public const string AppPropertiesName = "AppProperties";

    public IDictionary<string, object> Properties { get; set; }

    public AppProperty(IDictionary<string, object> appProperties)
    {
        Properties = appProperties;
    }
}

В приложении XAML.cs

UnityContainer container = new UnityContainer(); 
if (!IsUnitTestCase) 
{ 
    container.RegisterInstance<IDictionary<string, object>>(AppProperty.AppPropertiesName, Application.Current.Properties); 
} 
else 
{ 
    container.RegisterInstance<IDictionary<string, object>>(AppProperty.AppPropertiesName, new Dictionary<string,object>()); 
} 
container.RegisterType<IAppProperties,AppProperty>();
Application.Current.Resources.Add("Unity", container);

1 Ответ

2 голосов
/ 01 июля 2019

Если класс напрямую зависит от 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()
    { }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...