我如何测试使用VisualTreeHelper的东西?
我有这个静态帮助器功能:
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
var parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
var fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
//if it's not a ContentElement, rely on VisualTreeHelper
return VisualTreeHelper.GetParent(child);
}
它在一个真正的应用程序中工作,但我正在尝试为它编写一些单元测试。 这是我的第一次尝试:
[Test]
public void GetParentObject_returns_immediate_parent()
{
var contentControl = new ContentControl();
var textBox = new TextBox();
contentControl.BeginInit();
contentControl.Content = textBox;
contentControl.EndInit();
var result = UIHelper.GetParentObject(textBox);
Assert.AreSame(contentControl, result);
}
不幸的是,它失败了,因为VisualTreeHelper
返回null。 我怎样模拟一个可以工作的视觉树?
这就是静力学存在问题的原因。
您可以抽象接口后面的功能,并创建一个使用静态方法的默认实现。 然后,您可以使用依赖注入,这使得这个单元测试变得微不足道 - 模拟IVisualTreeHelper的依赖性,或者滚动您自己的存根实现,您可以配置它以返回您分配的任何值。
public class Foo
{
static IVisualTreeHelper visualTreeHelper;
static Foo()
{
Foo.visualTreeHelper = new FrameworkVisualTreeHelper();
}
public Foo(IVisualTreeHelper visualTreeHelper)
{
Foo.visualTreeHelper = visualTreeHelper;
}
public static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
var parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
var fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
//if it's not a ContentElement, rely on the IVisualTreeHelper
return visualTreeHelper.GetParent(child);
}
}
public interface IVisualTreeHelper
{
DependencyObject GetParent(DependencyObject reference);
}
public class FrameworkVisualTreeHelper : IVisualTreeHelper
{
public DependencyObject GetParent(DependencyObject reference)
{
return VisualTreeHelper.GetParent(reference);
}
}
显然,如果你在其他地方使用其他方法,你可能需要将其他VisualTreeHelper
方法添加到你的接口和默认实现中。
它仍然不是完全干净的,因为你正在测试的单元本身是静态的,当你尝试单元测试任何依赖于你的UIHelper类的静态方法的类时,你会遇到完全相同的问题。
基于这个答案在这里打印文件通过Wpf控制并转换为XPS我想出了以下扩展方法来创建视觉树。 它可以在没有STA线程或任何东西的情况下在NUnit中正常工作。
/// <summary>
/// Render a UIElement such that the visual tree is generated,
/// without actually displaying the UIElement
/// anywhere
/// </summary>
public static void CreateVisualTree(this UIElement element)
{
var fixedDoc = new FixedDocument();
var pageContent = new PageContent();
var fixedPage = new FixedPage();
fixedPage.Children.Add(element);
pageContent.ToMaybeOf<IAddChild>().Do(c => c.AddChild(fixedPage));
fixedDoc.Pages.Add(pageContent);
var f = new XpsSerializerFactory();
var w = f.CreateSerializerWriter(new MemoryStream());
w.Write(fixedDoc);
}
请注意
ToMaybeOf
东西基本上意味着将pageContent
作为IAddChild
对待,并在该接口上执行操作 嘲笑一个视觉树,你将不得不实际创建和渲染一个。 所以你将不得不创建一个实际的窗口,这对于单元测试并不特别理想。
链接地址: http://www.djcxy.com/p/3643.html上一篇: How can I unit test something that uses VisualTreeHelper?