Some extra resiliance and tests! Oh glorious tests.

This commit is contained in:
Ryan Nowak 2014-02-28 12:43:12 -08:00
parent bdd4513b88
commit 89eb6e6445
3 changed files with 243 additions and 4 deletions

View File

@ -1,6 +1,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Microsoft.AspNet.Routing
@ -17,10 +18,25 @@ namespace Microsoft.AspNet.Routing
{
if (obj != null)
{
foreach (var property in obj.GetType().GetTypeInfo().DeclaredProperties)
var type = obj.GetType();
var allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
// This is done to support 'new' properties that hide a property on a base class
var orderedByDeclaringType = allProperties.OrderBy(p => p.DeclaringType == type ? 0 : 1);
foreach (var property in orderedByDeclaringType)
{
var value = property.GetValue(obj);
Add(property.Name, value);
if (property.GetMethod != null && property.GetIndexParameters().Length == 0)
{
var value = property.GetValue(obj);
if (ContainsKey(property.Name) && property.DeclaringType != type)
{
// This is a hidden property, ignore it.
}
else
{
Add(property.Name, value);
}
}
}
}
}

View File

@ -1,7 +1,8 @@
using System;
namespace Microsoft.AspNet.Routing.Template.Tests
namespace Microsoft.AspNet.Routing
{
// Placeholder until we get our 'real' rich support for these asserts.
public class Assert : Xunit.Assert
{
public static T Throws<T>(Assert.ThrowsDelegate action, string message) where T : Exception

View File

@ -0,0 +1,222 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Dynamic;
using Xunit;
namespace Microsoft.AspNet.Routing.Tests
{
public class RouteValueDictionaryTests
{
[Fact]
public void CreateEmpty_UsesOrdinalIgnoreCase()
{
// Arrange
// Act
var dict = new RouteValueDictionary();
// Assert
Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer);
}
[Fact]
public void CreateFromDictionary_UsesOrdinalIgnoreCase()
{
// Arrange
// Act
var dict = new RouteValueDictionary(new Dictionary<string, object>(StringComparer.Ordinal));
// Assert
Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer);
}
[Fact]
public void CreateFromObject_UsesOrdinalIgnoreCase()
{
// Arrange
// Act
var dict = new RouteValueDictionary(new { cool = "beans" });
// Assert
Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromAnonymousType()
{
// Arrange
var obj = new {cool = "beans", awesome = 123};
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(2, dict.Count);
Assert.Equal("beans", dict["cool"]);
Assert.Equal(123, dict["awesome"]);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType()
{
// Arrange
var obj = new RegularType() { CoolnessFactor = 73};
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(2, dict.Count);
Assert.Equal(false, dict["IsAwesome"]);
Assert.Equal(73, dict["CoolnessFactor"]);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_PublicOnly()
{
// Arrange
var obj = new Visibility() { IsPublic = true, ItsInternalDealWithIt = 5 };
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(1, dict.Count);
Assert.Equal(true, dict["IsPublic"]);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_IgnoresStatic()
{
// Arrange
var obj = new StaticProperty();
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(0, dict.Count);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_IgnoresSetOnly()
{
// Arrange
var obj = new SetterOnly() {CoolSetOnly = false};
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(0, dict.Count);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_IncludesInherited()
{
// Arrange
var obj = new Derived() {TotallySweetProperty = true, DerivedProperty = false};
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(2, dict.Count);
Assert.Equal(true, dict["TotallySweetProperty"]);
Assert.Equal(false, dict["DerivedProperty"]);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_WithHiddenProperty()
{
// Arrange
var obj = new DerivedHiddenProperty() { DerivedProperty = 5 };
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(1, dict.Count);
Assert.Equal(5, dict["DerivedProperty"]);
}
[Fact]
public void CreateFromObject_CopiesPropertiesFromRegularType_WithIndexerProperty()
{
// Arrange
var obj = new IndexerProperty();
// Act
var dict = new RouteValueDictionary(obj);
// Assert
Assert.Equal(0, dict.Count);
}
[Fact]
public void CreateFromObject_MixedCaseThrows()
{
// Arrange
var obj = new { controller = "Home", Controller = "Home" };
// Act & Assert
Assert.Throws<ArgumentException>(
() => new RouteValueDictionary(obj),
"An item with the same key has already been added.");
}
private class RegularType
{
public bool IsAwesome { get; set; }
public int CoolnessFactor { get; set; }
}
private class Visibility
{
private string PrivateYo { get; set; }
internal int ItsInternalDealWithIt { get; set; }
public bool IsPublic { get; set; }
}
private class StaticProperty
{
public static bool IsStatic { get; set; }
}
private class SetterOnly
{
private bool _coolSetOnly;
public bool CoolSetOnly { set { _coolSetOnly = value; }}
}
private class Base
{
public bool DerivedProperty { get; set; }
}
private class Derived : Base
{
public bool TotallySweetProperty { get; set; }
}
private class DerivedHiddenProperty : Base
{
public new int DerivedProperty { get; set; }
}
private class IndexerProperty
{
public bool this[string key]
{
get { return false; }
set {}
}
}
}
}