代码之家  ›  专栏  ›  技术社区  ›  Tim Long

我怎样才能用moq模拟一个收藏呢

  •  11
  • Tim Long  · 技术社区  · 15 年前

    我对单元测试和模拟是全新的,而且还很不熟悉。我使用的是moq框架,我需要模拟一个集合,这样它将生成一个具有我提供的值的单个成员。

    所讨论的集合类是 System.Configuration.SettingsPropertyCollection ,其中包含 SettingsProperty 物体。

    反过来, 设置属性 有一个 Attributes 返回 SettingsAttributeDictionary .

    我需要我的收藏来制作一个单曲 设置属性 ,它有一个自定义属性(派生自 System.Attribute 在其 Attributes.SettingsAttributeDictionary .

    我真的在努力想办法解决这个问题,但到目前为止没有任何效果。我试过伸出我的舌头,用滑稽的脸去抓它,但没用。

    这是我迄今为止尝试的代码,在代码中注释的点处抛出异常,因此测试当然总是失败。

        [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在设备未注册时应返回默认值。引发异常:System.ArgumentException:类型System.Configuration.settingsContext实现ISerializable,但未能提供反序列化构造函数。

    1 回复  |  直到 14 年前
        1
  •  4
  •   Adam Ralph    15 年前

    我相信您需要设置mock settings属性的attributes属性以返回mock settings属性说明 然后 设置模拟设置的索引器attributedictionary以返回所需的值,例如

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

    编辑

    正在由moq使用的castle dynamicProxy类中引发异常。我认为这与MoQ如何嘲笑可序列化的对象有关。如果Castle在签名为(SerializationInfo,StreamingContext)的可序列化对象上找不到非公共构造函数,则会引发此异常。您可以做的是更改自定义settingsProvider的getPropertyValues方法,以便它接受哈希表而不是settingsContext,并为方法调用提供模拟哈希表而不是模拟settingsContext。hashtable具有所需的构造函数,因此这可能有效。坚持类型为settingsContext而不是hashTable的参数并没有真正的好处,因为settingsContext只是从hashTable派生的一个微不足道的参数,即它不添加任何成员。