首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Moq模拟集合?

如何使用Moq模拟集合?
EN

Stack Overflow用户
提问于 2010-02-05 21:01:43
回答 1查看 9.3K关注 0票数 11

我是全新的单元测试和嘲弄,仍然是湿背后的耳朵。我使用的是Moq框架,我需要模拟一个集合,这样它就产生了一个具有我提供的值的成员。

所讨论的集合类是System.Configuration.SettingsPropertyCollection,它包含SettingsProperty对象。

反过来,SettingsProperty有一个返回SettingsAttributeDictionaryAttributes属性。

我需要我的集合来生成一个SettingsProperty,它在其Attributes.SettingsAttributeDictionary中有一个自定义属性(从System.Attribute派生)。

我真的很难搞清楚这件事,但到目前为止还是没有用。我试着伸出舌头,对着它鬼鬼祟祟地做鬼脸,但都没有用。

下面是我已经尝试过的代码,在代码中注释的点会抛出一个异常,所以测试总是失败的。

代码语言:javascript
复制
    [TestMethod]
    public void GetPropertySettings_Should_Return_Default_Values_When_Device_Not_Registered()
        {
        const string deviceName = "My.UnitTest";
        const string deviceType = "Switch";
        var deviceId = String.Format("{0}.{1}", deviceName, deviceType);
        Mock<IProfile> mockProfile = new Mock<IProfile>();
        Mock<SettingsContext> mockSettingsContext = new Mock<SettingsContext>();
        // Construct a SettingsPropertyCollection populated with a single property.
        // The single property will have a fixed name and default value, and will also have a single
        // attribute, giving teh ASCOM DeviceId.
        var deviceAttribute = new ASCOM.DeviceIdAttribute(deviceId);
        var attributes = new SettingsAttributeDictionary();
        attributes.Add(typeof(DeviceIdAttribute), deviceAttribute);
        var settingsProperty = new SettingsProperty(SettingName, typeof(string), null, false, SettingDefaultValue, SettingsSerializeAs.String, attributes, true, true);
        var propertyCollection = new SettingsPropertyCollection();
        propertyCollection.Add(settingsProperty);

        // Now comes the interesting part where we call our IProfile - this is where we really need Moq.
        // Expectations:
        //  - mockProfile must have it's DeviceType set.
        //  - mockProfile's device type (captured in setDeviceType) must match deviceType.
        //  - The returned SettingsPropertyValueCollection must not be empty.
        //  - The returned SettingsPropertyValueCollection must have exactly one entry.
        //  - The entry must match the value of SettingDefaultValue. 

        // Expectation: IProfile must have its DeviceType set.  We capture the value into setDeviceType.
        var setDeviceType = String.Empty;
        mockProfile.SetupSet(x => x.DeviceType).Callback(y => setDeviceType = y);

        // Finally, it is time to call the method we want to test
        var settingsProvider = new SettingsProvider(mockProfile.Object);

        // THE NEXT LINE THROWS AN EXCEPTION
        // IF I TRY TO STEP INTO IT, IT NEVER RETURNS AND THE TEST RUN JUST ENDS.
        var result = settingsProvider.GetPropertyValues(mockSettingsContext.Object, propertyCollection);

        // Now lets verify that everything went as expected
        // First, let's test that the parsing of DeviceId was as expected: IProvider.DeviceType was set to the expected value
        Assert.AreEqual(deviceType, setDeviceType);
        // Then let's test that the methods of IProvider that we mocked were called
        mockProfile.VerifyAll();

        // With this done, let's turn to the output of the method
        // Firstly, we test that the resulting collection contains exactly one item of the type SettingsPropertyValue
        Assert.IsTrue(result.Count > 0);
        Assert.AreEqual(1, result.Count);
        Assert.IsTrue(result.OfType<SettingsPropertyValue>().Count() > 0);

        // Then let's inspect the contained SettingsProviderValue further
        var settingsPropertyValue = result.OfType<SettingsPropertyValue>().First();

        // First IsDirty flag must never be set
        Assert.IsFalse(settingsPropertyValue.IsDirty);

        // The PropertyValue must be the default value we passed in
        Assert.AreEqual(SettingDefaultValue, settingsPropertyValue.PropertyValue);
        }

抛出的异常(正如测试运行程序所报告的)是:

ASCOM.Platform.Test.SettingsProviderTest.GetPropertySettings_Should_Return_Default_Values_When_Device_Not_Registered抛出异常: System.ArgumentException:类型System.Configuration.SettingsContext实现ISerializable,但未能提供反序列化构造函数.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-02-05 21:16:30

我相信您需要设置模拟SettingsProperty的属性以返回模拟SettingsAttributeDictionary和,然后设置模拟SettingsAttributeDictionary的索引器以返回所需的值。

代码语言:javascript
复制
mockItem.SetupGet(x => x.Attributes).Returns(mockAttributes);

mockAttributes.SetupGet(x => x[It.IsAny<System.Type>()])
              .Returns(deviceAttribute);

编辑

异常将被抛出在由Moq使用的Castle类中。我相信这与Moq如何模拟可序列化的对象有关。如果在可序列化对象上找不到具有(SerializationInfo,StreamingContext)签名的非公共构造函数,那么它将抛出此异常。您可以做的是更改自定义SettingsProvider的SettingsProvider方法,以便它接受一个哈希表而不是一个SettingsContext,并为方法调用提供一个模拟哈希表而不是一个模拟SettingsContext。Hashtable有所需的构造函数,所以这可能会起作用。坚持使用类型为SettingsContext而不是Hashtable的参数并没有什么真正的好处,因为SettingsContext只是从Hashtable派生出来的,也就是说它没有添加任何成员。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2210392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档