如何使用Moq在不使用setter的情况下初始化复杂属性? - c#

问题:

我在使用Moq框架模拟Form的两个属性时遇到麻烦。有一些示例说明了如何执行我要在那里执行的操作,但是它们都具有类型简单的属性,例如stringint

FieldsIMainForm属性没有像MainForm那样被初始化,这对我来说为什么有意义(接口不允许这种类型的初始化发生)。我只是不知道该如何克服。

我有一个定义这样的形式:

public partial class MainForm : XtraForm, IMainForm
{
    ...

    #region Public Properties

    public RichEditDocumentServer DocServer { get; } = new RichEditDocumentServer();

    public Dictionary<string, string> Fields { get; } = new Dictionary<string, string>();

    #endregion

    ...
}

在我的测试中,夹具的设置如下:

...
#region Private Variables

private Mock<IConnector> _arc = new Mock<IConnector>();
private Mock<IMainForm> _arForm = new Mock<IMainForm>();
private MainController _controller;

#endregion

[TestFixtureSetUp]
public void FixtureSetup()
{
    _arc.SetupAllProperties();
    _arForm.SetupAllProperties();
    _controller = new MainController(_arc.Object)
    {
        View = _arForm.Object
    };
}
...

在测试中失败的行(但在使用UI运行时通过):

View.Fields.Add(...) // throws NullReferenceException because Fields in null

意向:

我不希望表单的公共接口允许将FieldsDocServer属性设置为初始设置以外的其他内容。但这仍然允许例如在.Add(...)属性上调用Fields。我打算测试将KeyValuePair添加到Fields是使更多业务逻辑类型的事情发生的成功步骤。

题:

不使用setter初始化复杂属性的Moq方法是什么?我的测试失败,因为这些属性是null。谢谢。

参考方案

您必须使用SetupGet方法;存在此方法来处理您要模拟getter方法的情况。(您可以使用常规的Setup代替SetupGet ...)

就像@Jeppe Stig Nielsen注释一样,您可以将方法设置为在每次调用时返回一个新实例,或者返回一个相同的实例。在您的情况下,您正在寻找选项B:

    private Mock<IConnector> _arc;
    private Mock<IMainForm> _arForm;
    private MainController _controller;
    private Dictionary<string, string> _fields;

    [TestFixtureSetUp]
    public void FixtureSetup()
    {
        _fields = new Dictionary<string, string>();
        _arc = new Mock<IConnector>();
        _arForm = new Mock<IMainForm>();

        //The magic line:
        _arForm.SetupGet(x => x.Fields).Returns(_fields);

        _controller = new MainController(_arc.Object)
        {
            View = _arForm.Object
        };
    }

上面的代码片段不会引发异常,并为您提供添加项的访问权限...

将谓词<T>转换为Func <T,bool> - c#

我有一个包含成员Predicate的类,希望在Linq表达式中使用该类:using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable&…

当我所有的都是T时,如何返回Interface <T>的实例? - java

我有一个界面:public interface ILoginResult<T> { public T get(); } 我有一个LoginPage对象:public class LoginPage<T> { ... public ILoginResult<T> login(...) { ... } } 我也有一些登录页面对…

客户端反序列化为数组序列化字典<string,string>数据 - c#

我有一个字典,该字典使用C#中的JavaScriptSerializer进行了序列化。在客户端,我有:"{"dd049eda-e289-4ca2-8841-4908f94d5b65":"2","ab969ac2-320e-42e1-b759-038eb7f57178":"5�…

Maven的Shade插件产生的罐子之间有什么区别? - java

在我的Maven项目中,我尝试使用maven-shade-plugin在运行mvn package时生成一个超级jar。结果,我的目标目录中出现三个jar:original-hello-world-0.1.0-SNAPSHOT.jar hello-world-0.1.0-SNAPSHOT.jar hello-world-0.1.0-SNAPSHOT-shad…

根据激活的Maven配置文件更新战争名称 - java

在pom中,我有两个配置文件。测试1测试2现在,我希望根据激活的配置文件更改战争名称。预期结果激活test1配置文件后,战争名称应为prefix-test1.war。激活test1和test2时,战争名称应为prefix-test1-test2.war。如果没有激活任何配置文件,则战争名称应为prefix.war。我的POM文件....<?xml ve…