namespace BuildingDirectory.Test; public sealed class MyDictionaryTests { [Fact] public void Add_Single() { const string Value = "test"; const int Key = 5; var dic = new MyDictionary(); dic.Add(Key, Value); dic.Count.Should().Be(1, "single item added"); dic.ContainsKey(Key).Should().BeTrue(); } [Fact] public void Add_Single_Object() { var value = new Foo(6, "hello"); const int Key = 5; var dic = new MyDictionary(); dic.Add(Key, value); dic.Count.Should().Be(1, "not only value but also reference types can be added"); dic.ContainsKey(Key).Should().BeTrue(); dic.TryGetValue(Key, out var returnedValue).Should().BeTrue(); returnedValue.Should().BeSameAs(value, "same reference returned"); } [Fact] public void Add_Single_Object_Null() { const int Key = 5; var dic = new MyDictionary(); dic.Add(Key, null); dic.Count.Should().Be(1, "null value can be valid if TValue is nullable"); dic.ContainsKey(Key).Should().BeTrue(); dic.TryGetValue(Key, out var returnedValue).Should().BeTrue(); returnedValue.Should().Be(null); } [Fact] public void Add_Multiple() { int[] keys = [10, 11, 12]; bool[] values = [true, false, true]; var dic = new MyDictionary(); for (var i = 0; i < keys.Length; i++) { dic.Add(keys[i], values[i]); } dic.Count.Should().Be(3, "three different items added"); for (var i = 0; i < keys.Length; i++) { int key = keys[i]; dic.ContainsKey(key).Should().BeTrue(); dic.TryGetValue(key, out bool value).Should().BeTrue(); value.Should().Be(values[i], "values can occur more than once"); } } [Fact] public void Add_Single_AlreadyExists() { const string Value1 = "test1"; const string Value2 = "test2"; const int Key = 5; var dic = new MyDictionary(); dic.Add(Key, Value1); dic.Add(Key, Value2); dic.Count.Should().Be(1, "single item added, then updated"); dic.ContainsKey(Key).Should().BeTrue(); dic.TryGetValue(Key, out string? value).Should().BeTrue("can be retrieved by key"); value.Should().Be(Value2, "initial value got updated"); } [Fact] public void GetKeys() { string[] keys = ["A", "B", "C"]; double[] values = [4D, 12.8D, -98.12D]; var dic = new MyDictionary(); for (var i = 0; i < keys.Length; i++) { dic.Add(keys[i], values[i]); } dic.GetKeys().Should().Contain(keys, "contains all added keys in unspecified order") .And.HaveCount(keys.Length); } [Fact] public void GetValues() { string[] keys = ["A", "B", "C"]; double[] values = [4D, 12.8D, -98.12D]; var dic = new MyDictionary(); for (var i = 0; i < keys.Length; i++) { dic.Add(keys[i], values[i]); } dic.GetValues().Should().Contain(values, "contains all added values in unspecified order") .And.HaveCount(values.Length); } [Fact] public void ContainsKey_NotExists() { var dic = new MyDictionary(); dic.Add(44, 120M); dic.ContainsKey(55).Should().BeFalse(); } [Fact] public void TryGetValue_NotExists() { var dic = new MyDictionary(); dic.Add(44, 120M); dic.TryGetValue(55, out decimal value).Should().BeFalse(); value.Should().Be(0, "if key not found assign default to out parameter"); } [Fact] public void Remove_Exists() { const int Key = 44; var dic = new MyDictionary(); dic.Add(Key, 120M); dic.Remove(Key).Should().BeTrue("could be removed"); dic.Count.Should().Be(0, "count reduced due to removal"); } [Fact] public void Remove_NotExists() { var dic = new MyDictionary(); dic.Add(44, 120M); dic.Remove(1234).Should().BeFalse("key not present in dictionary"); dic.Count.Should().Be(1, "count unchanged"); } [Fact] public void Indexer_Exists() { const int Key = 44; const decimal Value = 120M; var dic = new MyDictionary(); dic.Add(Key, Value); dic[Key].Should().Be(Value, "indexer access is possible"); } [Fact] public void Indexer_NotExists_Value() { var dic = new MyDictionary(); dic[44].Should().Be(0M, "not found so default decimal returned"); } [Fact] public void Indexer_NotExists_Object() { var dic = new MyDictionary(); dic[44].Should().BeNull("not found so default nullable returned"); } private record Foo(int Bar, string Baz); }