很少有具有Application.Current.Properties和Application.Current.SavePropertiesAsync
方法的方法。
那么我该如何测试其中包含这两种方法?在尝试为它们使用Unity容器后,我陷入了困境,但它仅适用于Properties,而不是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;
}
}
在App 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);
答案 0 :(得分:2)
如果一个类直接依赖于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()
{ }
}