1297 lines
54 KiB
C#
1297 lines
54 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
namespace ProductivityApiUnitTests
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Data.Entity;
|
|
using System.Data.Entity.Infrastructure;
|
|
using System.Data.Entity.Internal;
|
|
using System.Data.Entity.Resources;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
/// <summary>
|
|
/// General unit tests for DbPropertyValues and related classes/methods.
|
|
/// Some specific features, such as concurrency, are tested elsewhere.
|
|
/// </summary>
|
|
public class DbPropertyValuesTests : TestBase
|
|
{
|
|
#region Helper classes
|
|
|
|
private const BindingFlags PropertyBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
|
|
|
|
/// <summary>
|
|
/// A type with a variety of different types of properties used for the tests in this class.
|
|
/// </summary>
|
|
public class FakeTypeWithProps
|
|
{
|
|
public FakeTypeWithProps()
|
|
{
|
|
PublicNonNullStringProp = "NonNullValue";
|
|
}
|
|
|
|
public FakeTypeWithProps(
|
|
int id, string publicStringProp, string privateStringProp,
|
|
int publicIntProp, int privateIntProp,
|
|
int publicIntPropWithPrivateSetter, int publicIntPropWithPrivateGetter,
|
|
byte[] publicBinaryProp)
|
|
: this()
|
|
{
|
|
Id = id;
|
|
PublicStringProp = publicStringProp;
|
|
PrivateStringProp = privateStringProp;
|
|
PublicIntProp = publicIntProp;
|
|
PrivateIntProp = privateIntProp;
|
|
PublicIntPropWithPrivateSetter = publicIntPropWithPrivateSetter;
|
|
PublicIntPropWithPrivateGetter = publicIntPropWithPrivateGetter;
|
|
PublicBinaryProp = publicBinaryProp;
|
|
}
|
|
|
|
public virtual int Id { get; set; }
|
|
|
|
public virtual string PublicStringProp { get; set; }
|
|
public virtual string PublicNonNullStringProp { get; set; }
|
|
private string PrivateStringProp { get; set; }
|
|
|
|
public virtual string PublicReadonlyStringProp
|
|
{
|
|
get { return "PublicReadonlyStringProp"; }
|
|
}
|
|
|
|
private string PrivateReadonlyStringProp
|
|
{
|
|
get { return "PrivateReadonlyStringProp"; }
|
|
}
|
|
|
|
public virtual string PublicWriteOnlyStringProp
|
|
{
|
|
set { }
|
|
}
|
|
|
|
private string PrivateWriteOnlyStringProp
|
|
{
|
|
set { }
|
|
}
|
|
|
|
public virtual int PublicIntProp { get; set; }
|
|
private int PrivateIntProp { get; set; }
|
|
|
|
public virtual int PublicIntPropWithPrivateSetter { get; private set; }
|
|
public virtual int PublicIntPropWithPrivateGetter { private get; set; }
|
|
|
|
public virtual byte[] PublicBinaryProp { get; set; }
|
|
|
|
public virtual FakeTypeWithProps NestedObject { get; set; }
|
|
}
|
|
|
|
public class FakeDerivedTypeWithProps : FakeTypeWithProps
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for copying values to an object
|
|
|
|
[Fact]
|
|
public void Non_Generic_DbPropertyValues_uses_ToObject_on_InternalPropertyValues()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(properties));
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_for_entity_uses_CreateObject_to_return_instance_of_correct_type()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(null, isEntityValues: true);
|
|
values.MockInternalContext.Setup(c => c.CreateObject(typeof(FakeTypeWithProps))).Returns(new FakeDerivedTypeWithProps());
|
|
|
|
var clone = values.ToObject();
|
|
|
|
Assert.IsType<FakeDerivedTypeWithProps>(clone);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_for_complex_object_does_not_use_CreateObject_to_create_instance()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>();
|
|
|
|
var clone = values.ToObject();
|
|
|
|
values.MockInternalContext.Verify(c => c.CreateObject(typeof(FakeTypeWithProps)), Times.Never());
|
|
Assert.IsType<FakeTypeWithProps>(clone);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_sets_all_properties_from_the_dictionary_onto_the_object_including_those_with_private_setters()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "PublicStringProp", "PublicStringPropValue" },
|
|
{ "PrivateStringProp", "PrivateStringPropValue" },
|
|
{ "PublicIntProp", 2 },
|
|
{ "PrivateIntProp", 3 },
|
|
{ "PublicIntPropWithPrivateSetter", 4 },
|
|
{ "PublicIntPropWithPrivateGetter", 5 },
|
|
{ "PublicBinaryProp", new byte[] { 3, 1, 4, 1, 5, 9 } },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.Id);
|
|
Assert.Equal("PublicStringPropValue", clone.PublicStringProp);
|
|
Assert.Equal(2, clone.PublicIntProp);
|
|
Assert.Equal(
|
|
"PrivateStringPropValue",
|
|
typeof(FakeTypeWithProps).GetProperty("PrivateStringProp", PropertyBindingFlags).GetValue(clone, null));
|
|
Assert.Equal(3, typeof(FakeTypeWithProps).GetProperty("PrivateIntProp", PropertyBindingFlags).GetValue(clone, null));
|
|
Assert.Equal(4, clone.PublicIntPropWithPrivateSetter);
|
|
Assert.Equal(
|
|
5, typeof(FakeTypeWithProps).GetProperty("PublicIntPropWithPrivateGetter", PropertyBindingFlags).GetValue(clone, null));
|
|
Assert.True(DbHelpers.KeyValuesEqual(new byte[] { 3, 1, 4, 1, 5, 9 }, clone.PublicBinaryProp));
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_ignores_properties_that_are_conceptually_in_shadow_state()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "MissingProp", "MissingPropValue" }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_ignores_properties_that_are_readonly()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "PublicReadonlyStringProp", "Foo" },
|
|
{ "PrivateReadonlyStringProp", "Foo" }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.Id);
|
|
Assert.Equal("PublicReadonlyStringProp", clone.PublicReadonlyStringProp);
|
|
Assert.Equal(
|
|
"PrivateReadonlyStringProp",
|
|
typeof(FakeTypeWithProps).GetProperty("PrivateReadonlyStringProp", PropertyBindingFlags).GetValue(clone, null));
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_can_set_reference_propeties_to_null()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "PublicNonNullStringProp", null }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Null(clone.PublicNonNullStringProp);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_returns_nested_property_dictionary_as_cloned_object()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.NestedObject.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_ignores_null_nested_property_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "NestedObject", null }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var clone = (FakeTypeWithProps)values.ToObject();
|
|
|
|
Assert.Equal(1, clone.Id);
|
|
Assert.Null(clone.NestedObject);
|
|
}
|
|
|
|
[Fact]
|
|
public void ToObject_throws_when_trying_to_set_null_values_onto_non_nullable_properties()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(
|
|
new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
});
|
|
values["Id"] = null;
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_CannotSetNullValue("Id", "Int32", "FakeTypeWithProps"),
|
|
Assert.Throws<InvalidOperationException>(() => values.ToObject()).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for setting values from an object
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_null_object_throws()
|
|
{
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>());
|
|
|
|
Assert.Equal("obj", Assert.Throws<ArgumentNullException>(() => values.SetValues((object)null)).ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_copies_values_from_object_to_property_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "PublicStringProp", null },
|
|
{ "PrivateStringProp", null },
|
|
{ "PublicIntProp", 0 },
|
|
{ "PrivateIntProp", 0 },
|
|
{ "PublicIntPropWithPrivateSetter", 0 },
|
|
{ "PublicIntPropWithPrivateGetter", 0 },
|
|
{ "PublicBinaryProp", null },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var obj = new FakeTypeWithProps(
|
|
1, "PublicStringPropValue", "PrivateStringPropValue", 2, 3, 4, 5, new byte[] { 3, 1, 4, 1, 5, 9 });
|
|
|
|
values.SetValues(obj);
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
Assert.Equal("PublicStringPropValue", values["PublicStringProp"]);
|
|
Assert.Equal(2, values["PublicIntProp"]);
|
|
Assert.Equal("PrivateStringPropValue", values["PrivateStringProp"]);
|
|
Assert.Equal(3, values["PrivateIntProp"]);
|
|
Assert.Equal(4, values["PublicIntPropWithPrivateSetter"]);
|
|
Assert.Equal(5, values["PublicIntPropWithPrivateGetter"]);
|
|
Assert.True(DbHelpers.KeyValuesEqual(new byte[] { 3, 1, 4, 1, 5, 9 }, values["PublicBinaryProp"]));
|
|
}
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_object_of_differnt_type_copies_no_properties_if_no_properties_match()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "PublicStringProp", null },
|
|
{ "PrivateStringProp", null },
|
|
{ "PublicIntProp", 0 },
|
|
{ "PrivateIntProp", 0 },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
values.SetValues("Bang!");
|
|
|
|
Assert.Null(values["PublicStringProp"]);
|
|
Assert.Equal(0, values["PublicIntProp"]);
|
|
Assert.Null(values["PrivateStringProp"]);
|
|
Assert.Equal(0, values["PrivateIntProp"]);
|
|
}
|
|
|
|
public class FakeTypeWithSomeProps
|
|
{
|
|
public FakeTypeWithSomeProps(string publicStringProp, int privateIntProp, int someOtherIntProp)
|
|
{
|
|
PublicStringProp = publicStringProp;
|
|
PrivateIntProp = privateIntProp;
|
|
SomeOtherIntProp = someOtherIntProp;
|
|
}
|
|
|
|
public string PublicStringProp { get; set; }
|
|
private int PrivateIntProp { get; set; }
|
|
public int SomeOtherIntProp { get; set; }
|
|
}
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_object_of_differnt_type_copies_only_properties_that_match()
|
|
{
|
|
Attempt_to_copy_values_from_object_of_differnt_type_copies_only_properties_that_match_implementation(
|
|
new FakeTypeWithSomeProps("PublicStringPropValue", 3, 4));
|
|
}
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_anonymous_object_copies_only_properties_that_match()
|
|
{
|
|
var obj = new
|
|
{
|
|
PublicStringProp = "PublicStringPropValue",
|
|
PrivateIntProp = 3,
|
|
SomeDifferentIntProp = 4
|
|
};
|
|
Attempt_to_copy_values_from_object_of_differnt_type_copies_only_properties_that_match_implementation(obj);
|
|
}
|
|
|
|
private void Attempt_to_copy_values_from_object_of_differnt_type_copies_only_properties_that_match_implementation(object obj)
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "PublicStringProp", null },
|
|
{ "PrivateStringProp", null },
|
|
{ "PublicIntProp", 0 },
|
|
{ "PrivateIntProp", 0 },
|
|
{ "PublicIntPropWithPrivateSetter", 0 },
|
|
{ "PublicIntPropWithPrivateGetter", 0 },
|
|
{ "PublicBinaryProp", null },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
values.SetValues(obj);
|
|
|
|
Assert.Equal(0, values["Id"]);
|
|
Assert.Equal("PublicStringPropValue", values["PublicStringProp"]);
|
|
Assert.Equal(0, values["PublicIntProp"]);
|
|
Assert.Null(values["PrivateStringProp"]);
|
|
Assert.Equal(3, values["PrivateIntProp"]);
|
|
Assert.Equal(0, values["PublicIntPropWithPrivateSetter"]);
|
|
Assert.Equal(0, values["PublicIntPropWithPrivateGetter"]);
|
|
Assert.Null(values["PublicBinaryProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Non_Generic_DbPropertyValues_SetValues_works_on_the_underlying_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(properties));
|
|
|
|
values.SetValues(
|
|
new FakeTypeWithProps
|
|
{
|
|
Id = 1
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Calling_SetValues_with_instance_of_derived_type_works()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(properties));
|
|
|
|
values.SetValues(
|
|
new FakeDerivedTypeWithProps
|
|
{
|
|
Id = 1
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_ignores_properties_that_are_conceptually_in_shadow_state()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "MissingProp", "MissingPropValue" }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
values.SetValues(
|
|
new FakeTypeWithProps
|
|
{
|
|
Id = 1
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
Assert.Equal("MissingPropValue", values["MissingProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_ignores_properties_that_are_write_only()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "PublicWriteOnlyStringProp", "Foo" },
|
|
{ "PrivateWriteOnlyStringProp", "Bar" }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
values.SetValues(
|
|
new FakeTypeWithProps
|
|
{
|
|
Id = 1
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
Assert.Equal("Foo", values["PublicWriteOnlyStringProp"]);
|
|
Assert.Equal("Bar", values["PrivateWriteOnlyStringProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_can_set_reference_propeties_to_null()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "PublicStringProp", "NonNull" }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
values.SetValues(
|
|
new FakeTypeWithProps
|
|
{
|
|
Id = 1
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
Assert.Null(values["PublicStringProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_sets_values_from_complex_object_into_nested_property_dictionary()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
values.SetValues(
|
|
new FakeTypeWithProps
|
|
{
|
|
Id = 1,
|
|
NestedObject = new FakeTypeWithProps
|
|
{
|
|
Id = 2
|
|
}
|
|
});
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
Assert.Equal(2, nestedValues["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_when_complex_object_is_null_throws()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var obj = new FakeTypeWithProps
|
|
{
|
|
Id = 1,
|
|
NestedObject = null
|
|
};
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_ComplexObjectCannotBeNull("NestedObject", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<InvalidOperationException>(() => values.SetValues(obj)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_when_nested_property_dictionary_in_source_is_null_throws()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "NestedObject", null }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var obj = new FakeTypeWithProps
|
|
{
|
|
Id = 1,
|
|
NestedObject = new FakeTypeWithProps
|
|
{
|
|
Id = 2
|
|
}
|
|
};
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_NestedPropertyValuesNull("NestedObject", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<InvalidOperationException>(() => values.SetValues(obj)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_does_not_attempt_to_set_values_that_are_not_different()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "PublicStringProp", "PublicStringPropValue" },
|
|
{ "PublicIntProp", 2 },
|
|
{ "PublicBinaryProp", new byte[] { 3, 1, 4, 1, 5, 9 } },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var obj = new FakeTypeWithProps
|
|
{
|
|
PublicStringProp = "PublicStringPropValue",
|
|
PublicIntProp = 2,
|
|
PublicBinaryProp = new byte[] { 3, 1, 4, 1, 5, 9 }
|
|
};
|
|
|
|
values.SetValues(obj);
|
|
|
|
values.GetMockItem("PublicStringProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
values.GetMockItem("PublicIntProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
values.GetMockItem("PublicBinaryProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for copying values to a new dictionary
|
|
|
|
[Fact]
|
|
public void Non_Generic_DbPropertyValues_uses_Clone_on_InternalPropertyValues()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(properties));
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.Equal(1, clone["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_for_an_entity_returns_a_new_dictionary_that_is_also_for_an_entity()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(null, isEntityValues: true);
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.True(clone.IsEntityValues);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_for_a_complex_object_returns_a_new_dictionary_that_is_also_for_an_complex_object()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>();
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.False(clone.IsEntityValues);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_sets_all_properties_from_the_dictionary_into_the_new_values()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "PublicStringProp", "PublicStringPropValue" },
|
|
{ "PrivateStringProp", "PrivateStringPropValue" },
|
|
{ "PublicIntProp", 2 },
|
|
{ "PrivateIntProp", 3 },
|
|
{ "PublicIntPropWithPrivateSetter", 4 },
|
|
{ "PublicIntPropWithPrivateGetter", 5 },
|
|
{ "PublicBinaryProp", new byte[] { 3, 1, 4, 1, 5, 9 } },
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.Equal(1, clone["Id"]);
|
|
Assert.Equal("PublicStringPropValue", clone["PublicStringProp"]);
|
|
Assert.Equal(2, clone["PublicIntProp"]);
|
|
Assert.Equal("PrivateStringPropValue", clone["PrivateStringProp"]);
|
|
Assert.Equal(3, clone["PrivateIntProp"]);
|
|
Assert.Equal(4, clone["PublicIntPropWithPrivateSetter"]);
|
|
Assert.Equal(5, clone["PublicIntPropWithPrivateGetter"]);
|
|
Assert.True(DbHelpers.KeyValuesEqual(new byte[] { 3, 1, 4, 1, 5, 9 }, clone["PublicBinaryProp"]));
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_can_copy_null_properties()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "PublicNonNullStringProp", null }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.Null(clone["PublicNonNullStringProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_clones_nested_property_dictionary_into_new_cloned_nested_dictionary()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 2 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var clone = values.Clone();
|
|
var nestedClone = (InternalPropertyValues)clone["NestedObject"];
|
|
|
|
Assert.Equal(1, clone["Id"]);
|
|
Assert.Equal(2, nestedClone["Id"]);
|
|
|
|
Assert.False(clone.GetItem("Id").IsComplex);
|
|
Assert.True(clone.GetItem("NestedObject").IsComplex);
|
|
Assert.False(nestedClone.GetItem("Id").IsComplex);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_ignores_null_nested_property_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "NestedObject", null }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var clone = values.Clone();
|
|
|
|
Assert.Equal(1, clone["Id"]);
|
|
Assert.Null(clone["NestedObject"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Modifying_properties_on_cloned_dictionary_does_not_change_properties_on_original_dictionary_and_vice_versa()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 2 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 },
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var clone = values.Clone();
|
|
var nestedClone = (InternalPropertyValues)clone["NestedObject"];
|
|
|
|
values["Id"] = -1;
|
|
nestedValues["Id"] = -2;
|
|
clone["Id"] = -3;
|
|
nestedClone["Id"] = -4;
|
|
|
|
Assert.Equal(-1, values["Id"]);
|
|
Assert.Equal(-2, nestedValues["Id"]);
|
|
Assert.Equal(-3, clone["Id"]);
|
|
Assert.Equal(-4, nestedClone["Id"]);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for setting values from another dictionary
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_null_dictionary_on_non_generic_DbPropertyValues_throws()
|
|
{
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>());
|
|
|
|
Assert.Equal("propertyValues", Assert.Throws<ArgumentNullException>(() => values.SetValues(null)).ParamName);
|
|
}
|
|
|
|
[Fact]
|
|
public void Attempt_to_copy_values_from_dictionary_of_wrong_type_throws()
|
|
{
|
|
var values1 = new TestInternalPropertyValues<FakeDerivedTypeWithProps>();
|
|
var values2 = new TestInternalPropertyValues<FakeTypeWithProps>();
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_AttemptToSetValuesFromWrongType(
|
|
typeof(FakeTypeWithProps).Name, typeof(FakeDerivedTypeWithProps).Name),
|
|
Assert.Throws<ArgumentException>(() => values1.SetValues(values2)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_copies_values_from_one_dictionary_to_another_dictionary()
|
|
{
|
|
var fromValues = CreateSimpleValues();
|
|
fromValues["Id"] = 1;
|
|
fromValues["PublicStringProp"] = "PublicStringPropValue";
|
|
fromValues["PrivateStringProp"] = "PrivateStringPropValue";
|
|
fromValues["PublicIntProp"] = 2;
|
|
fromValues["PrivateIntProp"] = 3;
|
|
fromValues["PublicIntPropWithPrivateSetter"] = 4;
|
|
fromValues["PublicIntPropWithPrivateGetter"] = 5;
|
|
fromValues["PublicBinaryProp"] = new byte[] { 3, 1, 4, 1, 5, 9 };
|
|
|
|
var toValues = CreateSimpleValues();
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
Assert.Equal(1, toValues["Id"]);
|
|
Assert.Equal("PublicStringPropValue", toValues["PublicStringProp"]);
|
|
Assert.Equal(2, toValues["PublicIntProp"]);
|
|
Assert.Equal("PrivateStringPropValue", toValues["PrivateStringProp"]);
|
|
Assert.Equal(3, toValues["PrivateIntProp"]);
|
|
Assert.Equal(4, toValues["PublicIntPropWithPrivateSetter"]);
|
|
Assert.Equal(5, toValues["PublicIntPropWithPrivateGetter"]);
|
|
Assert.True(DbHelpers.KeyValuesEqual(new byte[] { 3, 1, 4, 1, 5, 9 }, toValues["PublicBinaryProp"]));
|
|
}
|
|
|
|
private TestInternalPropertyValues<FakeTypeWithProps> CreateSimpleValues()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 },
|
|
{ "PublicStringProp", null },
|
|
{ "PrivateStringProp", null },
|
|
{ "PublicIntProp", 0 },
|
|
{ "PrivateIntProp", 0 },
|
|
{ "PublicIntPropWithPrivateSetter", 0 },
|
|
{ "PublicIntPropWithPrivateGetter", 0 },
|
|
{ "PublicBinaryProp", null },
|
|
{ "NestedObject", nestedValues },
|
|
};
|
|
return new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
}
|
|
|
|
[Fact]
|
|
public void Non_Generic_DbPropertyValues_SetValues_with_a_dictionary_works_on_the_underlying_dictionary()
|
|
{
|
|
var fromValues = new DbPropertyValues(CreateSimpleValues());
|
|
fromValues["Id"] = 1;
|
|
|
|
var toValues = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
Assert.Equal(1, toValues["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Calling_SetValues_with_dictionary_of_derived_type_works()
|
|
{
|
|
var fromProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var fromValues = new DbPropertyValues(new TestInternalPropertyValues<FakeDerivedTypeWithProps>(fromProperties));
|
|
|
|
var toProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var toValues = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(toProperties));
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
Assert.Equal(1, toValues["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_with_dictionary_works_with_null_values()
|
|
{
|
|
var fromValues = CreateSimpleValues();
|
|
fromValues["Id"] = 1;
|
|
var toValues = CreateSimpleValues();
|
|
toValues["PublicStringProp"] = "Non-null";
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
Assert.Equal(1, toValues["Id"]);
|
|
Assert.Null(toValues["PublicStringProp"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_sets_nested_values_from_the_dictionary_into_nested_property_dictionary()
|
|
{
|
|
var fromValues = CreateSimpleValues();
|
|
fromValues["Id"] = 1;
|
|
((InternalPropertyValues)fromValues["NestedObject"])["Id"] = 2;
|
|
|
|
var toValues = CreateSimpleValues();
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
Assert.Equal(1, toValues["Id"]);
|
|
Assert.Equal(2, ((InternalPropertyValues)toValues["NestedObject"])["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_when_nested_dictionary_is_for_wrong_type_throws()
|
|
{
|
|
var fromProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var fromValues = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(fromProperties));
|
|
|
|
var toProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var toValues = new DbPropertyValues(new TestInternalPropertyValues<FakeDerivedTypeWithProps>(toProperties));
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_AttemptToSetValuesFromWrongType(
|
|
typeof(FakeTypeWithProps).Name, typeof(FakeDerivedTypeWithProps).Name),
|
|
Assert.Throws<ArgumentException>(() => toValues.SetValues(fromValues)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_when_nested_dictionary_in_source_is_null_throws()
|
|
{
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>();
|
|
|
|
var fromProperties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", null }
|
|
};
|
|
var fromValues = new TestInternalPropertyValues<FakeTypeWithProps>(fromProperties, new[] { "NestedObject" });
|
|
|
|
var toProperties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var toValues = new TestInternalPropertyValues<FakeTypeWithProps>(toProperties, new[] { "NestedObject" });
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_NestedPropertyValuesNull("NestedObject", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<InvalidOperationException>(() => toValues.SetValues(fromValues)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_when_nested_dictionary_in_target_is_null_throws()
|
|
{
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>();
|
|
|
|
var fromProperties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var fromValues = new TestInternalPropertyValues<FakeTypeWithProps>(fromProperties, new[] { "NestedObject" });
|
|
|
|
var toProperties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", null }
|
|
};
|
|
var toValues = new TestInternalPropertyValues<FakeTypeWithProps>(toProperties, new[] { "NestedObject" });
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_NestedPropertyValuesNull("NestedObject", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<InvalidOperationException>(() => toValues.SetValues(fromValues)).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetValues_from_another_dictionary_does_not_attempt_to_set_values_that_are_not_different()
|
|
{
|
|
var fromValues = CreateSimpleValues();
|
|
var toValues = CreateSimpleValues();
|
|
|
|
toValues.SetValues(fromValues);
|
|
|
|
toValues.GetMockItem("PublicStringProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
toValues.GetMockItem("PublicIntProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
toValues.GetMockItem("PublicBinaryProp").VerifySet(i => i.Value = It.IsAny<object>(), Times.Never());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for reading values from dictionarys
|
|
|
|
[Fact]
|
|
public void Scalar_values_can_be_read_from_a_property_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_can_be_read_from_a_property_dictionary()
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var readValues = (InternalPropertyValues)values["NestedObject"];
|
|
Assert.Equal(1, readValues["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reading_values_from_non_generic_DbPropertyValues_uses_the_internal_dictionary_and_returns_a_non_generic_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var values = new DbPropertyValues(new TestInternalPropertyValues<FakeTypeWithProps>(properties));
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reading_value_from_non_generic_DbPropertyValues_for_a_null_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("propertyName"),
|
|
Assert.Throws<ArgumentException>(() => { var _ = values[null]; }).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reading_value_from_non_generic_DbPropertyValues_for_an_empty_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("propertyName"), Assert.Throws<ArgumentException>(() => { var _ = values[""]; }).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reading_value_from_non_generic_DbPropertyValues_for_a_whitespace_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("propertyName"), Assert.Throws<ArgumentException>(() => { var _ = values[" "]; }).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reading_value_for_a_missing_property_name_throws()
|
|
{
|
|
var values = CreateSimpleValues();
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyDoesNotExist("NoSuchProperty", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<ArgumentException>(() => { var _ = values["NoSuchProperty"]; }).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for writing values into property values
|
|
|
|
[Fact]
|
|
public void Scalar_values_can_be_set_into_a_property_dictionary()
|
|
{
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(
|
|
new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
});
|
|
|
|
values["Id"] = 1;
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_can_be_set_at_the_complex_object_level_into_a_nested_property_dictionary()
|
|
{
|
|
SettingNestedValuesTest((values, nestedValues) => values["NestedObject"] = nestedValues);
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_can_be_set_at_the_complex_object_level_into_a_non_generic_dictionary_using_a_generic_dictionary()
|
|
{
|
|
SettingNestedValuesTest(
|
|
(values, nestedValues) => new DbPropertyValues(values)["NestedObject"] = new DbPropertyValues(nestedValues));
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_can_be_set_at_the_complex_object_level_into_a_non_generic_dictionary_using_a_non_generic_dictionary()
|
|
{
|
|
SettingNestedValuesTest(
|
|
(values, nestedValues) => new DbPropertyValues(values)["NestedObject"] = new DbPropertyValues(nestedValues));
|
|
}
|
|
|
|
private void SettingNestedValuesTest(Action<InternalPropertyValues, InternalPropertyValues> bagger)
|
|
{
|
|
var nestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
};
|
|
var nestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(nestedProperties);
|
|
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "NestedObject", nestedValues }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties, new[] { "NestedObject" });
|
|
|
|
var newNestedProperties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var newNestedValues = new TestInternalPropertyValues<FakeTypeWithProps>(newNestedProperties);
|
|
|
|
bagger(values, newNestedValues);
|
|
|
|
var readValues = (InternalPropertyValues)values["NestedObject"];
|
|
|
|
Assert.Same(nestedValues, readValues); // The nested dictionary itself has not changed
|
|
Assert.Equal(1, readValues["Id"]); // But the values in the dictionary have been copied.
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_cannot_be_set_to_null_in_a_property_dictionary()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_AttemptToSetNonValuesOnComplexProperty,
|
|
Assert.Throws<ArgumentException>(() => values["NestedObject"] = null).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Complex_values_cannot_be_set_to_actual_complex_object_instance_in_a_property_dictionary()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_AttemptToSetNonValuesOnComplexProperty,
|
|
Assert.Throws<ArgumentException>(() => values["NestedObject"] = new FakeTypeWithProps()).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Writing_values_to_non_generic_DbPropertyValues_uses_the_internal_dictionary()
|
|
{
|
|
var values = new DbPropertyValues(
|
|
new TestInternalPropertyValues<FakeTypeWithProps>(
|
|
new Dictionary<string, object>
|
|
{
|
|
{ "Id", 0 }
|
|
}));
|
|
|
|
values["Id"] = 1;
|
|
|
|
Assert.Equal(1, values["Id"]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Writing_values_to_non_generic_DbPropertyValues_for_a_null_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("propertyName"), Assert.Throws<ArgumentException>(() => values[null] = 0).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Writing_values_to_non_generic_DbPropertyValues_for_an_empty_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(Strings.ArgumentIsNullOrWhitespace("propertyName"), Assert.Throws<ArgumentException>(() => values[""] = 0).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Writing_values_to_non_generic_DbPropertyValues_for_a_whitespace_property_name_throws()
|
|
{
|
|
var values = new DbPropertyValues(CreateSimpleValues());
|
|
|
|
Assert.Equal(
|
|
Strings.ArgumentIsNullOrWhitespace("propertyName"), Assert.Throws<ArgumentException>(() => values[" "] = 0).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Writing_values_to_a_missing_property_name_throws()
|
|
{
|
|
var values = CreateSimpleValues();
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyDoesNotExist("NoSuchProperty", typeof(FakeTypeWithProps).Name),
|
|
Assert.Throws<ArgumentException>(() => values["NoSuchProperty"] = 0).Message);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tests for reading property names from a dictionary
|
|
|
|
[Fact]
|
|
public void Property_names_can_be_read_from_a_property_dictionary()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "One", 1 },
|
|
{ "Two", 2 },
|
|
{ "Three", 3 }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var names = values.PropertyNames;
|
|
|
|
Assert.Equal(3, names.Count);
|
|
Assert.True(names.Contains("One"));
|
|
Assert.True(names.Contains("Two"));
|
|
Assert.True(names.Contains("Three"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Property_names_are_returned_as_a_readonly_set()
|
|
{
|
|
var properties = new Dictionary<string, object>
|
|
{
|
|
{ "Id", 1 }
|
|
};
|
|
var values = new TestInternalPropertyValues<FakeTypeWithProps>(properties);
|
|
|
|
var names = values.PropertyNames;
|
|
|
|
Assert.True(names.IsReadOnly);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadOnlyHashSet_is_readonly_and_throws_for_mutating_methods()
|
|
{
|
|
var set = new ReadOnlySet<string>(new HashSet<string>());
|
|
|
|
Assert.True(set.IsReadOnly);
|
|
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyValueNamesAreReadonly,
|
|
Assert.Throws<NotSupportedException>(() => ((ICollection<string>)set).Add("")).Message);
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyValueNamesAreReadonly, Assert.Throws<NotSupportedException>(() => set.Add("")).Message);
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyValueNamesAreReadonly, Assert.Throws<NotSupportedException>(() => set.Clear()).Message);
|
|
Assert.Equal(
|
|
Strings.DbPropertyValues_PropertyValueNamesAreReadonly, Assert.Throws<NotSupportedException>(() => set.Remove("")).Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadOnlyHashSet_calls_underlying_Set_methods()
|
|
{
|
|
var mockSet = new Mock<ISet<string>>();
|
|
var mockIEnumerable = mockSet.As<IEnumerable>();
|
|
var set = new ReadOnlySet<string>(mockSet.Object);
|
|
var other = new HashSet<string>();
|
|
|
|
var array = new string[0];
|
|
set.CopyTo(array, 0);
|
|
mockSet.Verify(s => s.CopyTo(array, 0), Times.Once());
|
|
|
|
set.ExceptWith(other);
|
|
mockSet.Verify(s => s.ExceptWith(other), Times.Once());
|
|
|
|
set.IntersectWith(other);
|
|
mockSet.Verify(s => s.IntersectWith(other), Times.Once());
|
|
|
|
set.IsProperSubsetOf(other);
|
|
mockSet.Verify(s => s.IsProperSubsetOf(other), Times.Once());
|
|
|
|
set.IsProperSupersetOf(other);
|
|
mockSet.Verify(s => s.IsProperSupersetOf(other), Times.Once());
|
|
|
|
set.IsSubsetOf(other);
|
|
mockSet.Verify(s => s.IsSubsetOf(other), Times.Once());
|
|
|
|
set.IsSupersetOf(other);
|
|
mockSet.Verify(s => s.IsSupersetOf(other), Times.Once());
|
|
|
|
set.Overlaps(other);
|
|
mockSet.Verify(s => s.Overlaps(other), Times.Once());
|
|
|
|
set.SetEquals(other);
|
|
mockSet.Verify(s => s.SetEquals(other), Times.Once());
|
|
|
|
set.SymmetricExceptWith(other);
|
|
mockSet.Verify(s => s.SymmetricExceptWith(other), Times.Once());
|
|
|
|
set.UnionWith(other);
|
|
mockSet.Verify(s => s.UnionWith(other), Times.Once());
|
|
|
|
set.Contains("Foo");
|
|
mockSet.Verify(s => s.Contains("Foo"), Times.Once());
|
|
|
|
var _ = set.Count;
|
|
mockSet.Verify(s => s.Count, Times.Exactly(1));
|
|
|
|
mockSet.Setup(s => s.GetEnumerator()).Returns(Enumerable.Empty<string>().GetEnumerator());
|
|
set.GetEnumerator();
|
|
mockSet.Verify(s => s.GetEnumerator(), Times.Once());
|
|
|
|
mockIEnumerable.Setup(s => s.GetEnumerator()).Returns(Enumerable.Empty<string>().GetEnumerator());
|
|
((IEnumerable)set).GetEnumerator();
|
|
mockIEnumerable.Verify(s => s.GetEnumerator(), Times.Once());
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|