using System.Linq;
using System.Utility;
using NUnit.Framework;
namespace System.Collections.Generic
{
///
/// Tests for the type.
///
/// The type of the key.
/// The type of the value.
public abstract class DictionaryTests
: CollectionTests>
{
///
/// Initializes a new instance of the
/// class.
///
/// True if the order of iteration by
/// the should be tested, false if otherwise.
/// If you specify true, be sure to implement the
/// property.
protected DictionaryTests(bool testIterationOrder)
: this(testIterationOrder, EqualityComparer>.Default)
{}
///
/// Initializes a new instance of the
/// class.
///
/// True if the order of iteration by
/// the should be tested, false if otherwise.
/// If you specify true, be sure to implement the
/// property.
/// The that
/// is used to compare values in the for
/// uniqueness or null if the default
/// specified by is to be used.
protected DictionaryTests(bool testIterationOrder,
IEqualityComparer> comparer)
: base(testIterationOrder, comparer)
{}
////////////////////////////////////////////////////////////////////////
#region IDictionary.Add(TKey, TValue) Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.Add(TKey, TValue) " +
"throws an exception if the key is null. Note that this " +
"test assumes TKey can be null. If it cannot be override " +
"this test and have it ignored.")]
public virtual void AddArgumentNullException()
{
IDictionary dictionary = CreateDictionary();
Assert.Throws(() => dictionary.Add(default(TKey), default(TValue)));
}
[Test, Description("Ensures that IDictionary.Add(TKey, TValue) " +
"throws an exception if an element with the same key " +
"already exists in the dictionary.")]
public void ExceptionThrownWhenKeyAlreadyExists()
{
IDictionary dictionary = CreateDictionary();
var keyValue = CreateItem();
dictionary.Add(keyValue.Key, keyValue.Value);
Assert.Throws(() => dictionary.Add(keyValue.Key, keyValue.Value));
}
[Test, Description("Ensures that IDictionary.Add(TKey, TValue) " +
"throws an exception if it is called when the test is " +
"read only. Note that this test assumes the dictionary " +
"can be null. If it cannot be, override this test and " +
"have it ignored.")]
public virtual void AddNotSupportedExceptionWhenReadOnly()
{
IDictionary readOnlyDictionary = CreateReadOnlyDictionary();
if (readOnlyDictionary == null)
Assert.Ignore("IDictionary cannot be read-only.");
var keyValue = CreateItem();
Assert.Throws(() => readOnlyDictionary.Add(keyValue.Key, keyValue.Value));
}
[Test, Description("Ensures that IDictionary.Add(TKey, TValue) " +
"adds an item.")]
public void ItemIsAdded()
{
IDictionary dictionary = CreateDictionary();
var keyValue = CreateItem();
dictionary.Add(keyValue.Key, keyValue.Value);
TValue value = dictionary[keyValue.Key];
value.IsEqualTo(keyValue.Value, "dictionary value");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.ContainsKey(TKey) Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.ContainsKey(TKey) " +
"throws an exception if the key is null. Note that this " +
"test assumes TKey can be null. If it cannot be override " +
"this test and have it ignored.")]
public virtual void ContainsKeyArgumentNullException()
{
IDictionary dictionary = CreateDictionary();
Assert.Throws(() => dictionary.ContainsKey(default(TKey)));
}
[Test, Description("Ensures that IDictionary.ContainsKey(TKey) " +
"returns false when a key is not in the dictionary and" +
"true when it is.")]
public virtual void ContainsKeyReturnsTrueAndFalse()
{
IDictionary dictionary = CreateDictionary();
var keyValue = CreateItem();
Assert.False(dictionary.ContainsKey(keyValue.Key));
dictionary.Add(keyValue);
Assert.True(dictionary.ContainsKey(keyValue.Key));
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.Remove(TKey) Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.Remove(TKey) " +
"throws an exception if the key is null. Note that this " +
"test assumes TKey can be null. If it cannot be override " +
"this test and have it ignored.")]
public virtual void RemoveArgumentNullException()
{
IDictionary dictionary = CreateDictionary();
Assert.Throws(() => dictionary.Remove(default(TKey)));
}
[Test, Description("Ensures that IDictionary.Remove(TKey) " +
"throws a NotSupportedException if the IDictionary " +
"is read only. If the IDictionary cannot be read then " +
"this test is ignored.")]
public virtual void RemoveThrowsNotSupportedExceptionWhenDictionaryIsReadOnly()
{
IDictionary readOnlyDictionary = CreateReadOnlyDictionary();
if (readOnlyDictionary == null)
Assert.Ignore("IDictionary cannot be read-only.");
var item = readOnlyDictionary.First();
Assert.Throws(() => readOnlyDictionary.Remove(item.Key));
}
[Test, Description("Ensures that IDictionary.Remove(TKey) " +
"doesn't remove the item when it is not in the " +
"IDictionary and removes the item when " +
"it is.")]
public virtual void ItemRemovedAndNotRemoved()
{
IDictionary dictionary = CreateDictionary();
var item = CreateItem();
int countBeforeRemove = dictionary.Count;
Assert.False(dictionary.Remove(item.Key), "Item should not have been removed.");
dictionary.Count.IsEqualTo(countBeforeRemove, "IDictionary.Count");
dictionary.Add(item);
countBeforeRemove = dictionary.Count;
Assert.True(dictionary.Remove(item.Key));
dictionary.Count.IsNotEqualTo(countBeforeRemove, "IDictionary.Count");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.TryGetValue(TKey, TValue) Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.TryGetValue(TKey, TValue) " +
"throws an exception if the key is null. Note that this " +
"test assumes TKey can be null. If it cannot be override " +
"this test and have it ignored.")]
public virtual void TryGetValueArgumentNullException()
{
IDictionary dictionary = CreateDictionary();
TValue value;
Assert.Throws(() => dictionary.TryGetValue(default(TKey), out value));
}
[Test, Description("Ensures that IDictionary.TryGetValue(TKey, TValue) " +
"returns true if a value is in the IDictionary, false" +
"if otherwise.")]
public virtual void ItemRetrievedAndNotRetrieved()
{
IDictionary dictionary = CreateDictionary();
var item = CreateItem();
TValue retrievedItem;
Assert.False(dictionary.TryGetValue(item.Key, out retrievedItem),
"Item should not have been retrieved.");
// If the value could not be retrieved, then the item should have
// been set to the default value.
retrievedItem.IsEqualTo(default(TValue),
"IDictionary.TryGetValue(TKey, TValue)");
dictionary.Add(item);
Assert.True(dictionary.TryGetValue(item.Key, out retrievedItem));
retrievedItem.IsEqualTo(item.Value, "IDictionary.TryGetValue(TKey, TValue)");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.Keys Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.Keys " +
"contains the proper keys.")]
public virtual void KeysExpected()
{
IDictionary dictionary = CreateDictionary();
// Keys must exist for this test to work.
dictionary.Keys.Count.IsNotEqualTo(0, "IDictionary.Keys");
var keys = dictionary.Select(pair => pair.Key);
dictionary.Keys.IsEqualTo(keys, "IDictionary.Keys");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.this[TKey] Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.this[TKey] " +
"throws an exception if the key is null. Note that this " +
"test assumes TKey can be null. If it cannot be override " +
"this test and have it ignored.")]
public virtual void IndexerArgumentNullException()
{
IDictionary dictionary = CreateDictionary();
Assert.Throws(() => dictionary[default(TKey)] = default (TValue));
}
[Test, Description("Ensures that IDictionary.this[TKey] " +
"throws a KeyNotFoundException if the key cannot be " +
"found.")]
public virtual void KeyNotFoundException()
{
IDictionary dictionary = CreateDictionary();
var item = CreateItem();
Assert.Throws(() => Console.WriteLine(dictionary[item.Key]));
}
[Test, Description("Ensures that IDictionary.this[TKey] " +
"throws a NotSupportedException when the " +
"IDictionary is read only. If the " +
"IDictionary cannot be read then this " +
"test is ignored.")]
public virtual void IndexerThrowsNotSupportedExceptionWhenDictionaryIsReadOnly()
{
IDictionary readOnlyDictionary = CreateReadOnlyDictionary();
if (readOnlyDictionary == null)
Assert.Ignore("IDictionary cannot be read-only.");
var item = readOnlyDictionary.First();
Assert.Throws(() => Console.WriteLine(readOnlyDictionary[item.Key]));
}
[Test, Description("Ensures that IDictionary.this[TKey] " +
"returns the expected value.")]
public virtual void ItemRetrieved()
{
IDictionary dictionary = CreateDictionary();
var item = CreateItem();
dictionary.Add(item);
TValue retrievedItem = dictionary[item.Key];
retrievedItem.IsEqualTo(item.Value, "IDictionary.this[TKey]");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region IDictionary.Values Tests
////////////////////////////////////////////////////////////////////////
[Test, Description("Ensures that IDictionary.Values " +
"contains the proper keys.")]
public virtual void ValuesExpected()
{
IDictionary dictionary = CreateDictionary();
// Keys must exist for this test to work.
dictionary.Values.Count.IsNotEqualTo(0, "IDictionary.Values");
var values = dictionary.Select(pair => pair.Value);
dictionary.Values.IsEqualTo(values, "IDictionary.Values");
}
#endregion
////////////////////////////////////////////////////////////////////////
#region Overridables
////////////////////////////////////////////////////////////////////////
///
/// Creates an to test. The created
/// collection should contain the number of items specified by
/// . Each item
/// in the list should be unique so that a comparison of them does not
/// yield duplicates. This method should also create a collection that
/// follows the rules specified by the method
///
/// (see the comments on that method for details).
///
/// The instance to be tested.
protected abstract IDictionary CreateDictionary();
///
/// Creates a read-only to test.
/// This method should behave exactly like the
/// method and follow the exact same rules (see the comments on
/// for details). If the collection can
/// never be read-only, then this method should return null.
///
protected abstract IDictionary CreateReadOnlyDictionary();
protected override ICollection> CreateCollection()
{
return CreateDictionary();
}
protected override ICollection> CreateReadOnlyCollection()
{
return CreateReadOnlyDictionary();
}
#endregion
}
///
/// A test fixture that is used to test the
/// and to provide an example of
/// how to create a proper
/// test fixture.
///
[TestFixture]
public class DictionaryTestsFixture : DictionaryTests
{
public DictionaryTestsFixture()
: base(false)
{ }
#region Overridables
protected override IDictionary CreateDictionary()
{
IDictionary dictionary = new Dictionary();
for (int i = 0; i < RequiredCollectionCount; i++)
{
string indexStr = i.ToString();
dictionary.Add(indexStr, "Value " + indexStr);
}
return dictionary;
}
protected override IDictionary CreateReadOnlyDictionary()
{
// DictionaryTests cannot be read-only.
return null;
}
protected override KeyValuePair CreateItem()
{
string indexStr = (RequiredCollectionCount + 1).ToString();
return new KeyValuePair(indexStr, "Value " + indexStr);
}
#endregion
}
}