2

我正在为我的公司制作 Prism 模板。我想让设计时数据尽可能简单。

为此,我正在制作一个从我的 ViewModel 继承的设计类。DesignViewModel 将调用我的 ViewModel 的构造函数。

我的 ViewModel 构造函数有时会调用 prism 方法和属性,例如IRegionManager.Regions. 我正在考虑为将使用 NSubstitute 的接口制作一个存根。像这样:

public class DesginRegionManager : IRegionManager
{
    public IRegionManager CreateRegionManager(){return this;}

    private readonly IRegionCollection regions;
    public DesginRegionManager()
    {
        regions = Substitute.For<IRegionCollection>();   <--------
    }                                                            |
                                                                 |
    public IRegionCollection Regions {get { return regions; }}   |
}                                                                |
                                                                 |
// Using NSubstitute here ----------------------------------------

我打算为IUnityContainer.

除了单元测试,我从来没有在任何东西中使用过 Mocking 框架。像这样使用它是一个坏主意吗?

虽然它永远不会在生产代码中被调用,但它会为我的实际应用程序添加对 NSubstitute 的依赖。

这有缺点吗?

4

1 回答 1

3

在继续之前,尽管我以前使用过 caliburn,但我对 Prism 的经验很少,所以我假设它以类似的方式工作。但我确实对 nsubstitute 有一点经验。

将替代品用于设计目的是不是一个坏主意?

我的简短回答是否定的。

这并不完全理想,但是当您有一个设计部门(或在您继续编码时负责 UI 元素的人)时,将 UI 执行的代码与设计过程隔离开来是一种很好的做法,因为您将能够改进您的界面即使要实时执行的代码有问题。

当我说替代品时,我指的是由 Visual Studio 或 Blend 在设计时创建的真实(样本数据等)实例。(我将在最后提供一个样本)。

模拟这些元素是个坏主意吗?

也许不是,尽管您将在项目中包含更多对执行并不那么重要的依赖项。

它的积极方面是:

模拟定义意味着您将维护更少的代码,但您将无法在这些假实例上模拟数据(或者除非您开始为每个模拟返回样本数据)。

不利的一面:

首先,根据模拟框架,您将加载(在设计时)动态创建的代理或假货实例,以模拟某些行为拦截调用和其他内容。如果您创建大量不如实际代码轻量级的对象,这可能是一个痛苦的操作。

除了你的设计师(如果有一个混合大师)必须收集关于地狱 nsubstitute(或你喜欢的模拟框架)如何工作的知识。

如果我有一个设计师帽,并且您向我展示了一个具有特定定义的类,我可以复制该类与使用名为替代品的外部库定义的类,我可能会告诉您我更喜欢第一个选项,因为我不需要学习其他任何东西除了一点 c#。即使这样,我也不会尝试触及该代码。

将 nsubstitute 添加到您的项目有什么缺点吗?

只要您正确使用 DesignInstance 并且对带有模拟的代码的引用与实际功能隔离,并且您不尝试替换非虚拟属性或具有多个参数或密封类的实例(基本上 nsubstitute 对要替换的内容的任何限制)替代)你会没事的,因为设计属性将在你的代码的特殊模式下执行。

特别是 NSubstitute 可能会在尝试创建实例或访问某些属性时抛出异常,在这种情况下,IDE可能会在加载时崩溃或崩溃控件。

有样品吗?

你可能知道要写什么,但它就在这里(虽然不是棱镜)。

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/winfx/expression/blend/2008"
    xmlns:vm="clr-namespace:Project.Namespace.ViewModels.DataSamples"
    d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True, Type={x:Type NationViewModelSampleData}}">

    <StackPanel DataContext="{Binding Leader}">
        <TextBlock Text="{Binding FirstName}" />
        <TextBlock Text="{Binding LastName}" />
    </StackPanel>
</UserControl>

NationViewModel 在哪里实现了这样的接口

namespace Project.Namespace.ViewModels
{
    public interface INationViewModel
    {
        IPerson Leader { get; }
        IEnumerable<IPerson> Citizens { get; }
    }

    public interface IPerson
    {
        string FirstName { get; }
        string LastName { get; }
    }
}

样本数据为:

namespace Project.Namespace.ViewModels.DataSamples
{
    public class NationViewModelSampleData : Project.Namespace.ViewModels.INationViewModel
    {
        public NationViewModelSampleData()
        {
            // You could have done something like this as well, but for this sample was more code to write.
            // Leader = Substitute.For<IPerson>();
            // Leader.FirstName.Returns("John");
            // Leader.LastName.Returns("Doe");
            // or just...
            Leader = new Person { FirstName = "John", LastName = "Doe" };

            Citizens = new IPerson[]
                       {
                           new Person { FirstName = "Malcolm", LastName = "Little" },
                           Leader
                       };
            // You could have applied the mock to this section as well... again, more code for this scenario than just a simple real instance.
        }

        public IPerson Leader { get; private set; }
        public IEnumerable<IPerson> Citizens { get; private set; } 
    }
}

在这个示例中,我决定使用实际实例,因为我想象的 Person 实现非常小并且使用安全......但我希望它会变得越来越复杂如您之前所述,实例或模拟它。

希望这个评论有帮助。

干杯!

于 2012-05-18T06:27:17.233 回答