gpt4 book ai didi

c# - 自动化测试期间的 WPF 组件资源

转载 作者:太空狗 更新时间:2023-10-29 17:43:23 26 4
gpt4 key购买 nike

我已经到了想编写一个自动化测试来验证绑定(bind)到特定状态下的 View 模型的 WPF View 的内容的地步。

在概念上,它相当简单。创建一个 View 模型,设置它的状态,创建适当的 View ,将 View 添加到窗口,设置 View 的数据上下文,显示窗口,截取屏幕截图,与之前截取的屏幕截图进行比较。此类测试对于检测意外更改以及验证所有 View 实际上都可以无错误地创建非常有用。

但是,创建我的 View 实例被证明是有问题的。它需要一组未包含在 XAML 定义本身中的资源。这些资源在实际应用中包含在应用层的资源字典中,所以在实际应用中创建View的时候,这些资源已经可供它使用了。

当我在我的测试中创建这个 View 的实例时,它会抛出一个 XamlParseException 关于无法找到各种资源(可以理解)。

我不想简单地向 View 本身的 XAML 定义添加适当的资源字典,因为这会增加创建这些 View 对象之一所需的工作量(计算机工作量),以及增加每个所需的内存量实例。我的理解是,这是 ResourceDictionary 没有以这种方式共享的结果。

我试过了:

  • 在测试中创建 App.xaml 的实例(设置 Application.Current 属性)。
  • 将 Application.Current.Resources 属性设置为 App.xaml 实例的 Resources 属性。
  • 直接设置 Page 的 Resources 属性。
  • 直接设置 Window 的 Resources 属性(为测试添加页面的窗口)。

  • 本质上,我需要知道是否有办法设计一种情况,我可以为 WPF 组件的独立实例配置一组应用程序资源,以便在自动化测试中使用。

    您可以通过创建以下结构来重现该问题,除了 View_Test.cs 文件位于一个项目中,View_Test.cs 文件位于测试项目中。运行应用程序,它可以工作。运行测试,它失败了。

    应用程序.xaml
    <Application 
    x:Class="Blah.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
    <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Styles.xaml" />
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    </Application.Resources>
    </Application>

    样式文件
    <ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="SpecialBrush" Color="Black" />
    </ResourceDictionary>

    主窗口.xaml
    <Window 
    x:Class="Blah.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Blah="clr-namespace:Blah"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
    <Blah:View/>
    </Grid>
    </Window>

    查看.xaml
    <UserControl 
    x:Class="AutomatedTestUserControlApplicationResources.View"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="300">
    <Grid Background="{StaticResource SpecialBrush}">

    </Grid>
    </UserControl>

    View_Test.cs
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Blah;
    using System.Windows;

    namespace Blah.Test
    {
    [TestClass]
    public class View_Test
    {
    [TestMethod]
    public void Test()
    {
    var view = new View();

    var window = new Window();
    window.Content = view;

    window.ShowDialog();
    }
    }
    }

    更新:

    我很幸运为有问题的 View 创建了一个额外的构造函数,它采用 ResourceDictionary,作为一种向 View 注入(inject)一些上下文以进行初始化的方法。此构造函数重载仅用于测试,在实际应用程序中,资源上下文已经从应用程序资源中可用。
    public View(ResourceDictionary resourceContext = null)
    {
    if (resourceContext != null) Resources.MergedDictionaries.Add(resourceContext);
    InitializeComponent();
    }

    这解决了我上面发布的特定示例,它不依赖于初始化不相关的对象只是为了让 View 工作(这与良好的依赖注入(inject)实践背道而驰)。

    然而,当我试图在我的实际项目中实现它时,它带来了一些额外的问题。我在应用程序级别的资源上下文实际上是 4 个不同资源字典的合并,后者依赖于较早的(因为它们引用了较早条目中指定的资源)。

    应用资源.xaml
    <ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Style/GlobalColour.xaml"/>
    <ResourceDictionary Source="Style/GlobalBrush.xaml"/> <!-- Dependent on GlobalColour-->
    <ResourceDictionary Source="Style/GlobalStyle.xaml"/>
    <ResourceDictionary Source="Resources/GlobalContent.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

    在我的测试项目中从此文件创建一个 ResourceDictionary,然后在构建过程中将该 ResourceDictionary 注入(inject)我的 View 会引发与未找到 StaticResource 相关的 XamlParseException(无法找到的资源位于 GlobalBrush 中,并且依赖于 GlobalColour 中的条目) )。

    我会在进一步探索时更新。

    更新:

    我绝对没有运气手动创建和使用上面的 AppResources ResourceDictionary。我无法让 MergedDictionaries 中的词典之间的相互依赖发挥作用。我什至无法手动展平 ResourceDictionary 实例,因为当我尝试访问依赖于并行字典中资源的字典中的资源时,它抛出了 XamlParseException。

    因此,通过构造函数将 ResourceDictionary 注入(inject) View 的想法不适用于我的解决方案(尽管如果应用程序资源是平面 ResourceDictioanry,它可以工作)。

    在这次旅程的最后,我得出的结论是,在 xaml 不直接包含对资源的引用(无需实例化整个应用程序)的情况下,实例化 View 的唯一方法是在任何地方包含对适当 ResourceDictionary 的引用直接在 xaml 中使用资源。然后,您必须在运行时管理性能问题(因为您正在实例化数百个重复的 ResourceDictionaries),方法是使用 SharedResourceDictionary(互联网上有许多此概念的实现)。

    最佳答案

    这实际上并不是那么难,您只需要使用 Application.LoadComponent创建所有内容的实例,以便在正确的时间提供正确的资源。

    关键是通过其 XAML 加载所有内容,而不是创建类的实例,因为类只包含一半的信息。

    [TestClass]
    public class View_Test
    {
    [TestMethod]
    public void Test()
    {
    //set initial ResourceAssembly so we can load the App
    Application.ResourceAssembly = Assembly.GetAssembly(typeof (App));

    //load app
    var app = (App) Application.LoadComponent(new Uri("App.xaml", UriKind.Relative));

    //load window and assign to app
    var mainWindow = (Window) Application.LoadComponent(new Uri("MainWindow.xaml", UriKind.Relative));
    app.MainWindow = mainWindow;

    //load view and assign to window content
    var view = (UserControl) Application.LoadComponent(new Uri("View.xaml", UriKind.Relative));
    mainWindow.Content = view;

    //show the window
    mainWindow.Show();
    }
    }

    编辑:更简单的版本

    我只是看了一些反汇编的代码,看看它是如何在内部完成的,这可以简化为不需要 XAML 引用。使事情顺利进行的最重要的部分是设置 Application.ResourceAssembly并创建 App并调用 InitializeComponent在上面。该窗口不是特别必要的,您可以创建一个新窗口来保存 View 。
    [TestClass]
    public class View_Test
    {
    [TestMethod]
    public void Test()
    {
    Application.ResourceAssembly = Assembly.GetAssembly(typeof (App));

    var app = new App();
    app.InitializeComponent();

    var mainWindow = new MainWindow();
    app.MainWindow = mainWindow;

    var view = new View();
    mainWindow.Content = view;
    mainWindow.Show();
    }
    }

    关于c# - 自动化测试期间的 WPF 组件资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20797116/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com