using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace mustache.test { /// /// Tests the PropertyDictionary class. /// [TestClass] public class PropertyDictionaryTester { #region Real World Example /// /// The purpose of the PropertyDictionary class is to allow an object to be inspected, /// as if it were a dictionary. This means we can get and set properties by their names. /// [TestMethod] public void TestPropertyDictionary_AccessPropertiesViaIndexer() { var person = new { Name = "Bob", Age = 23, Birthday = new DateTime(2012, 03, 12) }; PropertyDictionary wrapper = new PropertyDictionary(person); Assert.AreEqual(3, wrapper.Count, "The wrong number of properties were created."); Assert.IsTrue(wrapper.ContainsKey("Name")); Assert.IsTrue(wrapper.ContainsKey("Age")); Assert.IsTrue(wrapper.ContainsKey("Birthday")); Assert.AreEqual(person.Name, wrapper["Name"], "The name was not wrapped."); Assert.AreEqual(person.Age, wrapper["Age"], "The age was not wrapped."); Assert.AreEqual(person.Birthday, wrapper["Birthday"], "The birthday was not wrapped."); } #endregion #region Ctor & Instance & IsReadOnly /// /// If we try to wrap null, an exception should be thrown. /// [TestMethod] public void TestCtor_NullInstance_ThrowsException() { PropertyDictionary dictionary = new PropertyDictionary(null); Assert.AreEqual(0, dictionary.Count); } /// /// We should be able to access the underlying object. /// [TestMethod] public void TestCtor_SetsInstance() { object instance = new object(); PropertyDictionary dictionary = new PropertyDictionary(instance); Assert.AreSame(instance, dictionary.Instance, "The instance was not set."); ICollection> collection = dictionary; Assert.IsTrue(collection.IsReadOnly, "The collection should not have been read-only."); } #endregion #region Add /// /// Since the dictionary is a simple wrapper around an object, we cannot add new properties. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestAdd_IDictionary_ThrowsException() { IDictionary dictionary = new PropertyDictionary(new object()); dictionary.Add("Name", "Bob"); } /// /// Since the dictionary is a simple wrapper around an object, we cannot add new properties. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestAdd_ICollection_ThrowsException() { ICollection> collection = new PropertyDictionary(new object()); collection.Add(new KeyValuePair("Name", "Bob")); } #endregion #region ContainsKey /// /// If the wrapped object has a property, the key should be found. /// [TestMethod] public void TestContainsKey_PropertyExists_ReturnsTrue() { var person = new { Name = "Bob", }; PropertyDictionary dictionary = new PropertyDictionary(person); bool result = dictionary.ContainsKey("Name"); Assert.IsTrue(result, "The property name was not found."); } /// /// If the wrapped object does not have a property, the key should not be found. /// [TestMethod] public void TestContainsKey_PropertyMissing_ReturnsFalse() { var person = new { }; PropertyDictionary dictionary = new PropertyDictionary(person); bool result = dictionary.ContainsKey("Name"); Assert.IsFalse(result, "The property name was found."); } private class BaseType { public string Inherited { get; set; } } private class DerivedType : BaseType { public string Local { get; set; } } /// /// We should be able to see properties defined in the base type. /// [TestMethod] public void TestContainsKey_PropertyInherited_ReturnsTrue() { BaseType b = new DerivedType(); PropertyDictionary dictionary = new PropertyDictionary(b); bool result = dictionary.ContainsKey("Inherited"); Assert.IsTrue(result, "The property name was not found."); } private class PrivateType { private string Hidden { get; set; } } /// /// We should not be able to see private properties. /// [TestMethod] public void TestContainsKey_PropertyPrivate_ReturnsFalse() { PrivateType t = new PrivateType(); PropertyDictionary dictionary = new PropertyDictionary(t); bool result = dictionary.ContainsKey("Hidden"); Assert.IsFalse(result, "The property name was found."); } private class StaticType { public static string Static { get; set; } } /// /// We should not be able to see static properties. /// [TestMethod] public void TestContainsKey_PropertyStatic_ReturnsFalse() { StaticType t = new StaticType(); PropertyDictionary dictionary = new PropertyDictionary(t); bool result = dictionary.ContainsKey("Static"); Assert.IsFalse(result, "The property name was found."); } #endregion #region Keys /// /// Keys should return the name of all of the property names in the object. /// [TestMethod] public void TestKeys_GetsAllPropertyNames() { var person = new { Name = "Bob", Age = 23 }; PropertyDictionary dictionary = new PropertyDictionary(person); ICollection keys = dictionary.Keys; Assert.AreEqual(2, keys.Count, "The wrong number of keys were returned."); Assert.IsTrue(keys.Contains("Name"), "The Name property was not found."); Assert.IsTrue(keys.Contains("Age"), "The Age property was not found."); } #endregion #region Remove /// /// Since a property dictionary is just a wrapper around an object, we cannot remove properties from it. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestRemove_IDictionary_ThrowsException() { object instance = new object(); IDictionary dictionary = new PropertyDictionary(instance); dictionary.Remove("Name"); } /// /// Since a property dictionary is just a wrapper around an object, we cannot remove properties from it. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestRemove_ICollection_ThrowsException() { object instance = new object(); ICollection> collection = new PropertyDictionary(instance); collection.Remove(new KeyValuePair("Name", "Whatever")); } #endregion #region TryGetValue /// /// If we try to get the value for a property that doesn't exist, false should returned and object set to null. /// [TestMethod] public void TestTryGetValue_NoSuchProperty_ReturnsFalse() { var instance = new { }; PropertyDictionary dictionary = new PropertyDictionary(instance); object value; bool result = dictionary.TryGetValue("Name", out value); Assert.IsFalse(result, "The property should not have been found."); Assert.IsNull(value, "The value should have been null."); } /// /// If we try to get the value for a property that doesn't exist, false should returned and object set to null. /// [TestMethod] public void TestTryGetValue_PropertyExists_ReturnsTrue() { var instance = new { Name = "Test" }; PropertyDictionary dictionary = new PropertyDictionary(instance); object value; bool result = dictionary.TryGetValue("Name", out value); Assert.IsTrue(result, "The property should have been found."); Assert.AreEqual(instance.Name, value, "The value should have equaled the wrapped property value."); } #endregion #region Values /// /// We should be able to get the value of all of the properties. /// [TestMethod] public void TestValues_GetsValues() { var instance = new { Name = "Bob", Age = 23 }; PropertyDictionary dictionary = new PropertyDictionary(instance); ICollection values = dictionary.Values; Assert.AreEqual(2, values.Count, "The wrong number of values were returned."); Assert.IsTrue(values.Contains("Bob"), "The value for Name was not found."); Assert.IsTrue(values.Contains(23), "The value for Age was not found."); } #endregion #region Indexer /// /// If we try to retrieve the value for a property that does not exist, an exception /// should be thrown. /// [TestMethod] [ExpectedException(typeof(KeyNotFoundException))] public void TestIndexer_Getter_NoSuchProperty_ThrowsException() { object instance = new object(); PropertyDictionary dictionary = new PropertyDictionary(instance); object value = dictionary["Name"]; } /// /// If we try to get a value for a property that exists, the value should /// be returned. /// [TestMethod] public void TestIndexer_Getter_PropertyExists_ReturnsValue() { var instance = new { Name = "Bob" }; PropertyDictionary dictionary = new PropertyDictionary(instance); object value = dictionary["Name"]; Assert.AreSame(instance.Name, value, "The wrong value was returned."); } /// /// If we try to set the value for a property, an exception should be thrown. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestIndexer_Setter_ThrowsException() { PropertyDictionary dictionary = new PropertyDictionary(new { Name = 123 }); dictionary["Name"] = 123; } #endregion #region Clear /// /// Since the dictionary is just a wrapper, Clear will simply throw an exception. /// [TestMethod] [ExpectedException(typeof(NotSupportedException))] public void TestClear_ThrowsException() { object instance = new object(); ICollection> dictionary = new PropertyDictionary(instance); dictionary.Clear(); } #endregion #region Contains /// /// Contains should find the key/value pair if both the key and value are equal. /// [TestMethod] public void TestContains_Explicit_PairExists_ReturnsTrue() { var person = new { Name = "Bob" }; ICollection> collection = new PropertyDictionary(person); bool contains = collection.Contains(new KeyValuePair("Name", "Bob")); Assert.IsTrue(contains, "Did not find the pair."); } /// /// Contains should not find the key/value pair if the keys are not equal. /// [TestMethod] public void TestContains_Explicit_KeyDoesNotMatch_ReturnsFalse() { var person = new { Name = "Bob" }; ICollection> collection = new PropertyDictionary(person); bool contains = collection.Contains(new KeyValuePair("Age", "Bob")); Assert.IsFalse(contains, "The pair should not have been found."); } /// /// Contains should not find the key/value pair if the values are not equal. /// [TestMethod] public void TestContains_Explicit_ValueDoesNotMatch_ReturnsFalse() { var person = new { Name = "Bob" }; ICollection> collection = new PropertyDictionary(person); bool contains = collection.Contains(new KeyValuePair("Name", "Sally")); Assert.IsFalse(contains, "The pair should not have been found."); } #endregion #region CopyTo /// /// CopyTo should copy the key/value pairs to an array, assuming there is enough room. /// [TestMethod] public void TestCopyTo_Explicit() { var instance = new { Name = "Bob", Age = 23 }; ICollection> collection = new PropertyDictionary(instance); KeyValuePair[] array = new KeyValuePair[collection.Count]; int arrayIndex = 0; collection.CopyTo(array, arrayIndex); Assert.IsTrue(array.Contains(new KeyValuePair("Name", "Bob")), "The name property was not found."); Assert.IsTrue(array.Contains(new KeyValuePair("Age", 23)), "The age property was not found."); } #endregion #region GetEnumerator /// /// All the items should be enumerated in the dictionary. /// [TestMethod] public void TestGetEnumerator_EnumeratesAllItems() { var instance = new { Name = "Bob", Age = 23 }; IEnumerable> dictionary = new PropertyDictionary(instance); Assert.IsTrue(enumerate(dictionary).Contains(new KeyValuePair("Name", "Bob")), "The first pair was not present."); Assert.IsTrue(enumerate(dictionary).Contains(new KeyValuePair("Age", 23)), "The second pair was not present."); } private static IEnumerable enumerate(IEnumerable enumerable) { List items = new List(); foreach (T item in enumerable) { items.Add(item); } return items; } /// /// All the items should be enumerated in the dictionary. /// [TestMethod] public void TestGetEnumerator_Explicit_EnumeratesAllItems() { var instance = new { Name = "Bob", Age = 23 }; IEnumerable dictionary = new PropertyDictionary(instance); Assert.IsTrue(enumerate(dictionary).Cast>().Contains(new KeyValuePair("Name", "Bob")), "The first pair was not present."); Assert.IsTrue(enumerate(dictionary).Cast>().Contains(new KeyValuePair("Age", 23)), "The second pair was not present."); } private static IEnumerable enumerate(IEnumerable enumerable) { ArrayList items = new ArrayList(); foreach (object item in enumerable) { items.Add(item); } return items; } #endregion } }