如何使用最小起订量初始化没有 setter 的复杂属性?
How do I initialize complex properties with no setter using Moq?
问题:
我在使用 Moq 框架模拟我的表单的两个属性时遇到问题。有一些关于如何做我想做的事情的例子,但它们都具有简单类型的属性,比如 string
或 int
.
IMainForm
的 Fields
属性 没有像 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
意向:
我不希望我的表单的 public 界面允许将 Fields
或 DocServer
属性设置为初始设置以外的其他内容。但这仍然允许 .Add(...)
在 Fields
属性 上被调用。我打算测试将 KeyValuePair
s 添加到 Fields
是使更多业务逻辑类型的事情发生的成功步骤。
问题:
没有 setter 的 Moq 初始化复杂属性的方法是什么?我的测试失败了,因为这些属性是 null
。谢谢。
你必须使用SetupGet
方法;此方法的存在是为了处理您想模拟 getter 方法的情况。(您可以使用常规 Setup
而不是 SetupGet
...)
作为@Jeppe Stig Nielsen 的评论,您可以将该方法设置为每次调用时 return 一个新实例或 return 同一实例。在您的情况下,您正在寻找选项 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
};
}
以上代码片段不会抛出异常并为您提供对添加项目的访问...
问题:
我在使用 Moq 框架模拟我的表单的两个属性时遇到问题。有一些关于如何做我想做的事情的例子,但它们都具有简单类型的属性,比如 string
或 int
.
IMainForm
的 Fields
属性 没有像 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
意向:
我不希望我的表单的 public 界面允许将 Fields
或 DocServer
属性设置为初始设置以外的其他内容。但这仍然允许 .Add(...)
在 Fields
属性 上被调用。我打算测试将 KeyValuePair
s 添加到 Fields
是使更多业务逻辑类型的事情发生的成功步骤。
问题:
没有 setter 的 Moq 初始化复杂属性的方法是什么?我的测试失败了,因为这些属性是 null
。谢谢。
你必须使用SetupGet
方法;此方法的存在是为了处理您想模拟 getter 方法的情况。(您可以使用常规 Setup
而不是 SetupGet
...)
作为@Jeppe Stig Nielsen 的评论,您可以将该方法设置为每次调用时 return 一个新实例或 return 同一实例。在您的情况下,您正在寻找选项 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
};
}
以上代码片段不会抛出异常并为您提供对添加项目的访问...