无法初始化模拟 class 的成员
Cannot initialize member of mocked class
我有一个包含成员的接口,如下所示:
public interface IDataLoader
{
//other stuff
// tools for loading the items to be processed from disk or cloud
CustomCollection ItemsToBeProcessed {get; set;}
}
我正在为使用这些系统的其他组件做 UT ItemsToBeProcessed
,我想避免加载的复杂性和依赖性。
在每个 UT 中,我想用特定的硬编码数据填充 ItemsToBeProcessed。然后将数据馈送到被测模块(处理器模块)并将输出与特定的硬编码预期数据进行比较。
我的问题是我无法初始化这个 ItemsToBeProcessed
我不明白为什么。
到目前为止,这是我的 UT:
[Test]
public void DataProcessor_TestData1_asExpected()
{
Mock<IDataLoader> mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
MainController.Loader = mokedAmplifier.Object;
if(MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
// here the MainController.Loader.ItemsToBeProcessed is still null.. why???
var TestData = LoadTestData("testData1.xml");
var ExpectedData = LoadExpectedData("ExpectedData1.xml")
MainConroller.Loader.ItemsToBeProcessed.AddRange(TestData);
var ProcessingModuleBeingTested = new ProcessingModule();
var results = ProcessingModuleBeingTested.Process(MainController.Loader.ItemsToBeProcessed);
Asert.isEqual(ExepctedData, results);
}
如何初始化这个成员?
在调用时将所需成员模拟为return可用对象。
var collection = new CustomCollection();
var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(collection);
//...
如果您希望模拟记住对 属性 所做的更改,请使用 SetupAllProperties
Specifies that the all properties on the mock should have "property behavior",
meaning that setting its value will cause it to be saved and later returned
when the property is requested. (this is also known as "stubbing"). The default
value for each property will be the one generated as specified by the
Moq.Mock.DefaultValue property for the mock.
var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
mokedAmplifier.SetupAllProperties(); //<--
MainController.Loader = mokedAmplifier.Object;
if(MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
//...
参考 Moq Quickstart 以帮助理解模拟框架。
A 属性 只不过是一个获取和设置方法。如果您为模拟实例分配一个值,您只需使用 setter 方法, 与 [=32] 没有任何关系=]-方法。因此,通过错误 Mock 为您创建一个类似于以下内容的 class:
class TheMockClass : IDataLoader
{
CustomCollection get_ItemsToBeProcessed { return whatever; }
void set_ItemsToBeProcessed { }
}
如果你给这个 class 的一个实例赋值什么都不会发生,因为 setter 绝对什么都不做(不确定具体的内部结构,但重要的是即使 setter 做任何事情,它与 getter).
中使用的内容无关
您会看到,当被嘲笑时,这两种方法没有任何共同点。所以你必须同步模拟。然而,通常将 getter 模拟为 return 你的价值就足够了,因为你只是 使用被模拟的值,而不是设置它。
mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(new CustomCollection());
您需要设置 属性:
mokedAmplifier.SetupAllProperties();
MainController.Loader = mokedAmplifier.Object;
if (MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
或
var coll = new CustomCollection();
mokedAmplifier.Setup(x => x.ItemsToBeProcessed).Returns(coll);
我有一个包含成员的接口,如下所示:
public interface IDataLoader
{
//other stuff
// tools for loading the items to be processed from disk or cloud
CustomCollection ItemsToBeProcessed {get; set;}
}
我正在为使用这些系统的其他组件做 UT ItemsToBeProcessed
,我想避免加载的复杂性和依赖性。
在每个 UT 中,我想用特定的硬编码数据填充 ItemsToBeProcessed。然后将数据馈送到被测模块(处理器模块)并将输出与特定的硬编码预期数据进行比较。
我的问题是我无法初始化这个 ItemsToBeProcessed
我不明白为什么。
到目前为止,这是我的 UT:
[Test]
public void DataProcessor_TestData1_asExpected()
{
Mock<IDataLoader> mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
MainController.Loader = mokedAmplifier.Object;
if(MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
// here the MainController.Loader.ItemsToBeProcessed is still null.. why???
var TestData = LoadTestData("testData1.xml");
var ExpectedData = LoadExpectedData("ExpectedData1.xml")
MainConroller.Loader.ItemsToBeProcessed.AddRange(TestData);
var ProcessingModuleBeingTested = new ProcessingModule();
var results = ProcessingModuleBeingTested.Process(MainController.Loader.ItemsToBeProcessed);
Asert.isEqual(ExepctedData, results);
}
如何初始化这个成员?
在调用时将所需成员模拟为return可用对象。
var collection = new CustomCollection();
var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(collection);
//...
如果您希望模拟记住对 属性 所做的更改,请使用 SetupAllProperties
Specifies that the all properties on the mock should have "property behavior", meaning that setting its value will cause it to be saved and later returned when the property is requested. (this is also known as "stubbing"). The default value for each property will be the one generated as specified by the Moq.Mock.DefaultValue property for the mock.
var mokedAmplifier = new Mock<IDataLoader>(MockBehavior.Loose);
mokedAmplifier.SetupAllProperties(); //<--
MainController.Loader = mokedAmplifier.Object;
if(MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
//...
参考 Moq Quickstart 以帮助理解模拟框架。
A 属性 只不过是一个获取和设置方法。如果您为模拟实例分配一个值,您只需使用 setter 方法, 与 [=32] 没有任何关系=]-方法。因此,通过错误 Mock 为您创建一个类似于以下内容的 class:
class TheMockClass : IDataLoader
{
CustomCollection get_ItemsToBeProcessed { return whatever; }
void set_ItemsToBeProcessed { }
}
如果你给这个 class 的一个实例赋值什么都不会发生,因为 setter 绝对什么都不做(不确定具体的内部结构,但重要的是即使 setter 做任何事情,它与 getter).
中使用的内容无关您会看到,当被嘲笑时,这两种方法没有任何共同点。所以你必须同步模拟。然而,通常将 getter 模拟为 return 你的价值就足够了,因为你只是 使用被模拟的值,而不是设置它。
mokedAmplifier.Setup(_ => _.ItemsToBeProcessed).Returns(new CustomCollection());
您需要设置 属性:
mokedAmplifier.SetupAllProperties();
MainController.Loader = mokedAmplifier.Object;
if (MainController.Loader.ItemsToBeProcessed == null)
MainController.Loader.ItemsToBeProcessed = new CustomCollection();
或
var coll = new CustomCollection();
mokedAmplifier.Setup(x => x.ItemsToBeProcessed).Returns(coll);