// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. namespace System.Data.Entity.Internal { using System.Data.Entity.Core.Objects.DataClasses; using System.Data.Entity.Resources; using System.Threading; using Xunit; public class InternalReferenceEntryTests { public class CurrentValue { [Fact] public void InternalReferenceEntry_gets_current_value_from_entity_if_property_exists() { InternalReferenceEntry_gets_current_value_from_entity_if_property_exists_implementation(isDetached: false); } [Fact] public void InternalReferenceEntry_gets_current_value_from_entity_even_when_detached_if_property_exists() { InternalReferenceEntry_gets_current_value_from_entity_if_property_exists_implementation(isDetached: true); } private void InternalReferenceEntry_gets_current_value_from_entity_if_property_exists_implementation(bool isDetached) { var relatedEntity = new FakeEntity(); var entity = new FakeWithProps { Reference = relatedEntity }; var internalEntry = new InternalReferenceEntry( MockHelper.CreateMockInternalEntityEntry( entity, isDetached).Object, FakeWithProps.ReferenceMetadata); var propValue = internalEntry.CurrentValue; Assert.Same(relatedEntity, propValue); } [Fact] public void InternalReferenceEntry_sets_current_value_onto_entity_if_property_exists() { InternalReferenceEntry_sets_current_value_onto_entity_if_property_exists_implementation(isDetached: false); } [Fact] public void InternalReferenceEntry_sets_current_value_onto_entity_even_when_detached_if_property_exists() { InternalReferenceEntry_sets_current_value_onto_entity_if_property_exists_implementation(isDetached: true); } private void InternalReferenceEntry_sets_current_value_onto_entity_if_property_exists_implementation(bool isDetached) { var entity = new FakeWithProps { Reference = new FakeEntity() }; var internalEntry = new InternalReferenceEntry( MockHelper.CreateMockInternalEntityEntry(entity, isDetached).Object, FakeWithProps.ReferenceMetadata); var relatedEntity = new FakeEntity(); internalEntry.CurrentValue = relatedEntity; Assert.Same(relatedEntity, entity.Reference); } [Fact] public void InternalReferenceEntry_gets_current_value_from_RelatedEnd_if_navigation_property_has_been_removed_from_entity() { InternalReferenceEntry_gets_current_value_from_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (new FakeEntity()); } [Fact] public void InternalReferenceEntry_gets_null_from_RelatedEnd_if_navigation_property_has_been_removed_from_entity_and_no_value_is_set() { InternalReferenceEntry_gets_current_value_from_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (null); } private void InternalReferenceEntry_gets_current_value_from_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (FakeEntity relatedEntity) { var mockRelatedEnd = Core.Objects.DataClasses.MockHelper.CreateMockEntityReference(relatedEntity); var internalEntry = new InternalReferenceEntry( MockHelper.CreateMockInternalEntityEntry(new FakeEntity(), mockRelatedEnd.Object).Object, FakeWithProps.ReferenceMetadata); var propValue = internalEntry.CurrentValue; Assert.Same(relatedEntity, propValue); } [Fact] public void InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity() { InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (new FakeEntity(), new FakeEntity()); } [Fact] public void InternalReferenceEntry_sets_null_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity() { InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (new FakeEntity(), null); } [Fact] public void InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_when_current_value_is_null () { InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (null, new FakeEntity()); } [Fact] public void InternalReferenceEntry_sets_null_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_when_current_value_and_new_value_are_both_null () { InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (null, null); } [Fact] public void InternalReferenceEntry_does_not_set_anything_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_when_current_value_and_new_value_are_same () { var relatedEntity = new FakeEntity(); InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (relatedEntity, relatedEntity); } /// /// Validates that the call to set a value on an is made as /// expected without mocking EntityReference (since it is sealed). This could be dones with Moq /// but it turned out easier and clearer this way. /// internal class FakeInternalReferenceEntry : InternalReferenceEntry { public FakeInternalReferenceEntry(InternalEntityEntry internalEntityEntry, NavigationEntryMetadata navigationMetadata) : base(internalEntityEntry, navigationMetadata) { } protected override void SetNavigationPropertyOnRelatedEnd(object value) { SetCount++; ValueSet = value; } public object ValueSet { get; set; } public int SetCount { get; set; } } private void InternalReferenceEntry_sets_current_value_onto_RelatedEnd_if_navigation_property_has_been_removed_from_entity_implementation (FakeEntity currentRelatedEntity, FakeEntity newRelatedEntity) { var mockRelatedEnd = Core.Objects.DataClasses.MockHelper.CreateMockEntityReference(currentRelatedEntity); var internalEntry = new FakeInternalReferenceEntry( MockHelper.CreateMockInternalEntityEntry(new FakeEntity(), mockRelatedEnd.Object).Object, FakeWithProps.ReferenceMetadata); internalEntry.CurrentValue = newRelatedEntity; Assert.Equal(1, internalEntry.SetCount); Assert.Same(newRelatedEntity, internalEntry.ValueSet); } [Fact] public void InternalReferenceEntry_throws_getting_current_value_from_detached_entity_if_navigation_property_has_been_removed() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_NotSupportedForDetached("CurrentValue", "Reference", "FakeEntity"), Assert.Throws(() => { var _ = internalEntry.CurrentValue; }).Message); } [Fact] public void InternalReferenceEntry_throws_setting_current_value_from_detached_entity_if_navigation_property_has_been_removed() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_SettingEntityRefNotSupported("Reference", "FakeEntity", "Detached"), Assert.Throws(() => { internalEntry.CurrentValue = null; }).Message); } } public class Load { [Fact] public void InternalReferenceEntry_Load_throws_if_used_with_Detached_entity() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_NotSupportedForDetached("Load", "Reference", "FakeEntity"), Assert.Throws(() => internalEntry.Load()).Message); } } #if !NET40 public class LoadAsync { [Fact] public void InternalReferenceEntry_LoadAsync_throws_if_used_with_Detached_entity() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_NotSupportedForDetached("LoadAsync", "Reference", "FakeEntity"), Assert.Throws( () => internalEntry.LoadAsync(CancellationToken.None).Wait()).Message); } } #endif public class IsLoaded { [Fact] public void InternalReferenceEntry_IsLoaded_throws_if_used_with_Detached_entity() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_NotSupportedForDetached("IsLoaded", "Reference", "FakeEntity"), Assert.Throws(() => { var _ = internalEntry.IsLoaded; }).Message); } } public class Name { [Fact] public void InternalReferenceEntry_Name_works_even_when_used_with_Detached_entity() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal("Reference", internalEntry.Name); } } public class Query { [Fact] public void InternalReferenceEntry_Query_throws_if_used_with_Detached_entity() { var mockInternalEntry = MockHelper.CreateMockInternalEntityEntry( new FakeEntity(), isDetached: true); var internalEntry = new InternalReferenceEntry(mockInternalEntry.Object, FakeWithProps.ReferenceMetadata); Assert.Equal( Strings.DbPropertyEntry_NotSupportedForDetached("Query", "Reference", "FakeEntity"), Assert.Throws(() => internalEntry.Query()).Message); } } } }