This repository has been archived by the owner on Jan 24, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated model binding to support fields as well as properties.
Replaced references to PropertyInfo in the binding code with a new class BindingMemberInfo, which can refer to either PropertyInfo or FieldInfo objects. Turned the reflection code into a utility method Collect() on the new class. Updated existing unit tests and added new ones.
- Loading branch information
Showing
9 changed files
with
607 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
235 changes: 235 additions & 0 deletions
235
src/Nancy.Tests/Unit/ModelBinding/BindingMemberInfoFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
namespace Nancy.Tests.Unit.ModelBinding | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Xml.Serialization; | ||
using Nancy.ModelBinding; | ||
using Xunit; | ||
using Xunit.Sdk; | ||
|
||
public class BindingMemberInfoFixture | ||
{ | ||
[Fact] | ||
public void Should_return_MemberInfo_for_properties_or_fields() | ||
{ | ||
// Given | ||
var type = typeof(TestModel); | ||
var underlyingFieldInfo = type.GetFields().First(); | ||
var underlyingPropertyInfo = type.GetProperties().First(); | ||
|
||
// When | ||
var fieldInfo = new BindingMemberInfo(underlyingFieldInfo); | ||
var propertyInfo = new BindingMemberInfo(underlyingPropertyInfo); | ||
|
||
// Then | ||
fieldInfo.MemberInfo.ShouldEqual(underlyingFieldInfo); | ||
propertyInfo.MemberInfo.ShouldEqual(underlyingPropertyInfo); | ||
} | ||
|
||
[Fact] | ||
public void Should_return_Name_for_properties_or_fields() | ||
{ | ||
// Given | ||
var type = typeof(TestModel); | ||
var underlyingFieldInfo = type.GetFields().First(); | ||
var underlyingPropertyInfo = type.GetProperties().First(); | ||
|
||
// When | ||
var fieldInfo = new BindingMemberInfo(underlyingFieldInfo); | ||
var propertyInfo = new BindingMemberInfo(underlyingPropertyInfo); | ||
|
||
// Then | ||
fieldInfo.Name.ShouldEqual(underlyingFieldInfo.Name); | ||
propertyInfo.Name.ShouldEqual(underlyingPropertyInfo.Name); | ||
} | ||
|
||
[Fact] | ||
public void Should_return_PropertyType_for_properties_or_fields() | ||
{ | ||
// Given | ||
var properties = BindingMemberInfo.Collect<TestModel>(); | ||
|
||
// When | ||
|
||
// Then | ||
properties.ShouldHaveCount(4); | ||
|
||
foreach (var propInfo in properties) | ||
{ | ||
if (propInfo.Name.StartsWith("Int")) | ||
{ | ||
propInfo.PropertyType.ShouldEqual(typeof(int)); | ||
} | ||
else if (propInfo.Name.StartsWith("String")) | ||
{ | ||
propInfo.PropertyType.ShouldEqual(typeof(string)); | ||
} | ||
else | ||
{ | ||
throw new AssertException("Internal error in unit test: Test model property/field name does not follow the expected convention: " + propInfo.Name); | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public void Should_get_fields() | ||
{ | ||
// Given | ||
var propInfo = BindingMemberInfo.Collect<TestModel>().Where(prop => prop.Name.EndsWith("Field")); | ||
var model = new TestModel(); | ||
|
||
// When | ||
model.IntField = 669; | ||
model.StringField = "testing"; | ||
|
||
// Then | ||
propInfo.Single(prop => prop.PropertyType == typeof(int)) | ||
.GetValue(model) | ||
.ShouldEqual(669); | ||
|
||
propInfo.Single(prop => prop.PropertyType == typeof(string)) | ||
.GetValue(model) | ||
.ShouldEqual("testing"); | ||
} | ||
|
||
[Fact] | ||
public void Should_set_fields() | ||
{ | ||
// Given | ||
var propInfo = BindingMemberInfo.Collect<TestModel>().Where(prop => prop.Name.EndsWith("Field")); | ||
var model = new TestModel(); | ||
|
||
// When | ||
propInfo.Single(prop => prop.PropertyType == typeof(int)) | ||
.SetValue(model, 42); | ||
|
||
propInfo.Single(prop => prop.PropertyType == typeof(string)) | ||
.SetValue(model, "nineteen"); | ||
|
||
// Then | ||
model.IntField.ShouldEqual(42); | ||
model.StringField.ShouldEqual("nineteen"); | ||
} | ||
|
||
[Fact] | ||
public void Should_get_properties() | ||
{ | ||
// Given | ||
var propInfo = BindingMemberInfo.Collect<TestModel>().Where(prop => prop.Name.EndsWith("Property")); | ||
var model = new TestModel(); | ||
|
||
// When | ||
model.IntProperty = 1701; | ||
model.StringProperty = "NancyFX Unit Testing"; | ||
|
||
// Then | ||
propInfo.Single(prop => prop.PropertyType == typeof(int)) | ||
.GetValue(model) | ||
.ShouldEqual(1701); | ||
|
||
propInfo.Single(prop => prop.PropertyType == typeof(string)) | ||
.GetValue(model) | ||
.ShouldEqual("NancyFX Unit Testing"); | ||
} | ||
|
||
[Fact] | ||
public void Should_set_properties() | ||
{ | ||
// Given | ||
var propInfo = BindingMemberInfo.Collect<TestModel>().Where(prop => prop.Name.EndsWith("Property")); | ||
var model = new TestModel(); | ||
|
||
// When | ||
propInfo.Single(prop => prop.PropertyType == typeof(int)) | ||
.SetValue(model, 2600); | ||
|
||
propInfo.Single(prop => prop.PropertyType == typeof(string)) | ||
.SetValue(model, "R2D2"); | ||
|
||
// Then | ||
model.IntProperty.ShouldEqual(2600); | ||
model.StringProperty.ShouldEqual("R2D2"); | ||
} | ||
|
||
[Fact] | ||
public void Should_collect_all_bindable_members_and_skip_all_others() | ||
{ | ||
// Given | ||
|
||
// When | ||
var properties = BindingMemberInfo.Collect<BiggerTestModel>(); | ||
|
||
// Then | ||
properties.ShouldHaveCount(16); | ||
|
||
foreach (var property in properties) | ||
property.Name.ShouldStartWith("Bindable"); | ||
} | ||
|
||
public class TestModel | ||
{ | ||
public int IntField; | ||
public string StringField; | ||
|
||
public int IntProperty { get; set; } | ||
public string StringProperty { get; set; } | ||
} | ||
|
||
public class BiggerTestModel | ||
{ | ||
public int BindableIntField; | ||
public int BindableIntProperty { get; set; } | ||
public string BindableStringField; | ||
public string BindableStringProperty { get; set; } | ||
public TestModel BindableTestModelField; | ||
public TestModel BindableTestModelProperty { get; set; } | ||
public BiggerTestModel BindableBiggerTestModelField; | ||
public BiggerTestModel BindableBiggerTestModelProperty { get; set; } | ||
[XmlIgnore] | ||
public IEnumerable<int> BindableEnumerableField; | ||
[XmlIgnore] | ||
public IEnumerable<int> BindableEnumerableProperty { get; set; } | ||
public List<string> BindableListField; | ||
public List<string> BindableListProperty { get; set; } | ||
public double[] BindableArrayField; | ||
public double[] BindableArrayProperty { get; set; } | ||
public TestModel[] BindableArrayOfObjectsField; | ||
public TestModel[] BindableArrayOfObjectsProperty { get; set; } | ||
|
||
public int this[int index] | ||
{ | ||
get { return 0; } | ||
set { } | ||
} | ||
|
||
public int this[string index, int index2] | ||
{ | ||
get { return 0; } | ||
set { } | ||
} | ||
|
||
public readonly int UnbindableReadOnlyField = 74205; | ||
|
||
public string UnbindableReadOnlyProperty | ||
{ | ||
get { return "hi"; } | ||
} | ||
|
||
public string UnbindableWriteOnlyProperty | ||
{ | ||
set { } | ||
} | ||
|
||
private int UnbindablePrivateField; | ||
|
||
public static int UnbindableStaticField; | ||
|
||
public static int UnbindableStaticProperty | ||
{ | ||
get { return 0; } | ||
set { } | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.