PageRenderTime 77ms CodeModel.GetById 2ms app.highlight 67ms RepoModel.GetById 2ms app.codeStats 0ms

/test/EntityFramework/UnitTests/DatabindingTests.cs

https://bitbucket.org/vanickdigital/totus.entityframework
C# | 1051 lines | 848 code | 199 blank | 4 comment | 2 complexity | 4fc973a6e94ef4d6a471f20bf8f6d990 MD5 | raw file
   1// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
   2
   3namespace System.Data.Entity
   4{
   5    using System;
   6    using System.Collections.Generic;
   7    using System.Collections.ObjectModel;
   8    using System.ComponentModel;
   9    using System.Data.Entity.Infrastructure;
  10    using System.Data.Entity.Internal;
  11    using System.Data.Entity.Internal.Linq;
  12    using System.Data.Entity.Resources;
  13    using System.Linq;
  14    using System.Reflection;
  15    using System.Xml.Linq;
  16    using Moq;
  17    using Xunit;
  18
  19    /// <summary>
  20    /// Unit tests for data binding and DbSet.Local.
  21    /// </summary>
  22    public class DatabindingTests : TestBase
  23    {
  24        #region Test subjects
  25
  26        private class ListElement
  27        {
  28            public ListElement()
  29            {
  30            }
  31
  32            public ListElement(int i)
  33            {
  34                Int = i;
  35                NullableInt = i;
  36                String = i.ToString();
  37                XNode = new XText(i.ToString());
  38                Random = new Random();
  39                ByteArray = new[] { (byte)i, (byte)i, (byte)i, (byte)i };
  40            }
  41
  42            public static implicit operator ListElement(int i)
  43            {
  44                return new ListElement(i);
  45            }
  46
  47            public int Int { get; set; }
  48            public int? NullableInt { get; set; }
  49            public string String { get; set; }
  50            public XNode XNode { get; set; }
  51            public Random Random { get; set; }
  52            public byte[] ByteArray { get; set; }
  53
  54            public static PropertyDescriptor Property(string name)
  55            {
  56                return TypeDescriptor.GetProperties(typeof(ListElement))[name];
  57            }
  58        }
  59
  60        private class DerivedListElement : ListElement
  61        {
  62            public DerivedListElement()
  63            {
  64            }
  65
  66            public DerivedListElement(int i)
  67                : base(i)
  68            {
  69            }
  70        }
  71
  72        private class ListElementComparer : IEqualityComparer<ListElement>
  73        {
  74            public bool Equals(ListElement x, ListElement y)
  75            {
  76                return x.Int == y.Int;
  77            }
  78
  79            public int GetHashCode(ListElement obj)
  80            {
  81                return obj.Int;
  82            }
  83        }
  84
  85        #endregion
  86
  87        #region SortableBindingList tests
  88
  89        private void SortTest(string property, ListSortDirection direction)
  90        {
  91            var list = new List<ListElement>
  92                           {
  93                               3,
  94                               1,
  95                               4,
  96                               1,
  97                               5,
  98                               9
  99                           };
 100            var sortedList = direction == ListSortDirection.Ascending
 101                                 ? new List<ListElement>
 102                                       {
 103                                           1,
 104                                           1,
 105                                           3,
 106                                           4,
 107                                           5,
 108                                           9
 109                                       }
 110                                 : new List<ListElement>
 111                                       {
 112                                           9,
 113                                           5,
 114                                           4,
 115                                           3,
 116                                           1,
 117                                           1
 118                                       };
 119
 120            var bindingList = new SortableBindingList<ListElement>(list);
 121
 122            ((IBindingList)bindingList).ApplySort(ListElement.Property(property), direction);
 123
 124            Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
 125        }
 126
 127        [Fact]
 128        public void SortableBindingList_can_sort_ascending_using_IComparable_on_value_type()
 129        {
 130            SortTest("Int", ListSortDirection.Ascending);
 131        }
 132
 133        [Fact]
 134        public void SortableBindingList_can_sort_ascending_using_IComparable_on_nullable_value_type()
 135        {
 136            SortTest("NullableInt", ListSortDirection.Ascending);
 137        }
 138
 139        [Fact]
 140        public void SortableBindingList_can_sort_ascending_using_IComparable_on_reference_type()
 141        {
 142            SortTest("String", ListSortDirection.Ascending);
 143        }
 144
 145        [Fact]
 146        public void SortableBindingList_can_sort_descending_using_IComparable_on_value_type()
 147        {
 148            SortTest("Int", ListSortDirection.Descending);
 149        }
 150
 151        [Fact]
 152        public void SortableBindingList_can_sort_descending_using_IComparable_on_nullable_value_type()
 153        {
 154            SortTest("NullableInt", ListSortDirection.Descending);
 155        }
 156
 157        [Fact]
 158        public void SortableBindingList_can_sort_descending_using_IComparable_on_reference_type()
 159        {
 160            SortTest("String", ListSortDirection.Descending);
 161        }
 162
 163        [Fact]
 164        public void SortableBindingList_can_sort_ascending_for_XNode_using_ToString()
 165        {
 166            SortTest("XNode", ListSortDirection.Ascending);
 167        }
 168
 169        [Fact]
 170        public void SortableBindingList_can_sort_descending_for_XNode_using_ToString()
 171        {
 172            SortTest("XNode", ListSortDirection.Descending);
 173        }
 174
 175        [Fact]
 176        public void SortableBindingList_does_not_sort_for_non_XNode_that_does_not_implement_IComparable()
 177        {
 178            var list = new List<ListElement>
 179                           {
 180                               3,
 181                               1,
 182                               4,
 183                               1,
 184                               5,
 185                               9
 186                           };
 187            var unsortedList = new List<ListElement>
 188                                   {
 189                                       3,
 190                                       1,
 191                                       4,
 192                                       1,
 193                                       5,
 194                                       9
 195                                   };
 196            var bindingList = new SortableBindingList<ListElement>(list);
 197
 198            ((IBindingList)bindingList).ApplySort(ListElement.Property("Random"), ListSortDirection.Ascending);
 199
 200            Assert.True(list.SequenceEqual(unsortedList, new ListElementComparer()));
 201        }
 202
 203        [Fact]
 204        public void SortableBindingList_does_not_sort_for_byte_arrays()
 205        {
 206            var list = new List<ListElement>
 207                           {
 208                               3,
 209                               1,
 210                               4,
 211                               1,
 212                               5,
 213                               9
 214                           };
 215            var unsortedList = new List<ListElement>
 216                                   {
 217                                       3,
 218                                       1,
 219                                       4,
 220                                       1,
 221                                       5,
 222                                       9
 223                                   };
 224            var bindingList = new SortableBindingList<ListElement>(list);
 225
 226            ((IBindingList)bindingList).ApplySort(ListElement.Property("ByteArray"), ListSortDirection.Descending);
 227
 228            Assert.True(list.SequenceEqual(unsortedList, new ListElementComparer()));
 229        }
 230
 231        [Fact]
 232        public void SortableBindingList_can_sort_when_list_contains_derived_objects()
 233        {
 234            var list = new List<ListElement>
 235                           {
 236                               new DerivedListElement(3),
 237                               new DerivedListElement(1),
 238                               new DerivedListElement(4)
 239                           };
 240            var sortedList = new List<ListElement>
 241                                 {
 242                                     new DerivedListElement(1),
 243                                     new DerivedListElement(3),
 244                                     new DerivedListElement(4)
 245                                 };
 246
 247            var bindingList = new SortableBindingList<ListElement>(list);
 248
 249            ((IBindingList)bindingList).ApplySort(ListElement.Property("Int"), ListSortDirection.Ascending);
 250
 251            Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
 252        }
 253
 254        [Fact]
 255        public void SortableBindingList_can_sort_when_list_is_of_derived_type()
 256        {
 257            var list = new List<DerivedListElement>
 258                           {
 259                               new DerivedListElement(3),
 260                               new DerivedListElement(1),
 261                               new DerivedListElement(4)
 262                           };
 263            var sortedList = new List<DerivedListElement>
 264                                 {
 265                                     new DerivedListElement(1),
 266                                     new DerivedListElement(3),
 267                                     new DerivedListElement(4)
 268                                 };
 269
 270            var bindingList = new SortableBindingList<DerivedListElement>(list);
 271
 272            ((IBindingList)bindingList).ApplySort(ListElement.Property("Int"), ListSortDirection.Ascending);
 273
 274            Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
 275        }
 276
 277        #endregion
 278
 279        #region ObservableBackedBindingList tests
 280
 281        [Fact]
 282        public void Items_added_to_ObservableCollection_are_added_to_binding_list()
 283        {
 284            var oc = new ObservableCollection<ListElement>();
 285            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 286
 287            var item = new ListElement(1);
 288            oc.Add(item);
 289
 290            Assert.True(obbl.Contains(item));
 291        }
 292
 293        [Fact]
 294        public void Items_removed_from_ObservableCollection_are_removed_from_binding_list()
 295        {
 296            var item = new ListElement(4);
 297            var oc = new ObservableCollection<ListElement>
 298                         {
 299                             3,
 300                             1,
 301                             item,
 302                             1,
 303                             5,
 304                             9
 305                         };
 306            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 307
 308            oc.Remove(item);
 309
 310            Assert.False(obbl.Contains(item));
 311            Assert.Equal(5, obbl.Count);
 312        }
 313
 314        [Fact]
 315        public void Items_replaced_in_the_ObservableCollection_are_replaced_in_the_binding_list()
 316        {
 317            var item = new ListElement(4);
 318            var oc = new ObservableCollection<ListElement>
 319                         {
 320                             3,
 321                             1,
 322                             item,
 323                             1,
 324                             5,
 325                             9
 326                         };
 327            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 328
 329            var newItem = new ListElement(-4);
 330            oc[2] = newItem;
 331
 332            Assert.False(obbl.Contains(item));
 333            Assert.True(obbl.Contains(newItem));
 334            Assert.Equal(6, obbl.Count);
 335        }
 336
 337        [Fact]
 338        public void Items_cleared_in_the_ObservableCollection_are_cleared_in_the_binding_list()
 339        {
 340            var oc = new ObservableCollection<ListElement>
 341                         {
 342                             3,
 343                             1,
 344                             4,
 345                             1,
 346                             5,
 347                             9
 348                         };
 349            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 350
 351            oc.Clear();
 352
 353            Assert.Equal(0, obbl.Count);
 354        }
 355
 356        [Fact]
 357        public void Adding_duplicate_item_to_the_ObservableCollection_adds_duplicate_to_the_binding_list()
 358        {
 359            var item = new ListElement(4);
 360            var oc = new ObservableCollection<ListElement>
 361                         {
 362                             3,
 363                             1,
 364                             item,
 365                             1,
 366                             5,
 367                             9
 368                         };
 369            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 370
 371            oc.Add(item);
 372
 373            Assert.Equal(7, obbl.Count);
 374            Assert.Equal(2, obbl.Count(i => ReferenceEquals(i, item)));
 375        }
 376
 377        [Fact]
 378        public void Items_added_to_the_binding_list_are_added_to_the_ObservableCollection()
 379        {
 380            var oc = new ObservableCollection<ListElement>();
 381            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 382
 383            var item = new ListElement(7);
 384            obbl.Add(item);
 385
 386            Assert.True(oc.Contains(item));
 387        }
 388
 389        [Fact]
 390        public void Items_added_to_the_binding_list_with_AddNew_are_added_to_the_ObservableCollection()
 391        {
 392            var oc = new ObservableCollection<ListElement>();
 393            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 394
 395            var item = obbl.AddNew();
 396            obbl.EndNew(0);
 397
 398            Assert.True(oc.Contains(item));
 399        }
 400
 401        [Fact]
 402        public void Items_canceled_during_AddNew_are_not_added_to_the_ObservableCollection()
 403        {
 404            var oc = new ObservableCollection<ListElement>();
 405            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 406
 407            var item = obbl.AddNew();
 408            obbl.CancelNew(0);
 409
 410            Assert.False(oc.Contains(item));
 411        }
 412
 413        [Fact]
 414        public void Items_inserted_into_the_binding_list_are_added_to_the_ObservableCollection()
 415        {
 416            var oc = new ObservableCollection<ListElement>();
 417            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 418
 419            var item = new ListElement(7);
 420            obbl.Insert(0, item);
 421
 422            Assert.True(oc.Contains(item));
 423        }
 424
 425        [Fact]
 426        public void Items_set_in_the_binding_list_are_replaced_in_the_ObservableCollection()
 427        {
 428            var item = new ListElement(4);
 429            var oc = new ObservableCollection<ListElement>
 430                         {
 431                             3,
 432                             1,
 433                             item,
 434                             1,
 435                             5,
 436                             9
 437                         };
 438            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 439
 440            var newItem = new ListElement(7);
 441            obbl[2] = newItem;
 442
 443            Assert.True(oc.Contains(newItem));
 444            Assert.False(oc.Contains(item));
 445        }
 446
 447        [Fact]
 448        public void Items_removed_from_the_binding_list_are_removed_from_the_ObservableCollection()
 449        {
 450            var item = new ListElement(4);
 451            var oc = new ObservableCollection<ListElement>
 452                         {
 453                             3,
 454                             1,
 455                             item,
 456                             1,
 457                             5,
 458                             9
 459                         };
 460            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 461
 462            obbl.Remove(item);
 463
 464            Assert.False(oc.Contains(item));
 465        }
 466
 467        [Fact]
 468        public void Items_removed_by_index_from_the_binding_list_are_removed_from_the_ObservableCollection()
 469        {
 470            var item = new ListElement(4);
 471            var oc = new ObservableCollection<ListElement>
 472                         {
 473                             3,
 474                             1,
 475                             item,
 476                             1,
 477                             5,
 478                             9
 479                         };
 480            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 481
 482            obbl.RemoveAt(2);
 483
 484            Assert.False(oc.Contains(item));
 485        }
 486
 487        [Fact]
 488        public void Items_cleared_from_the_binding_list_are_cleared_from_the_ObservableCollection()
 489        {
 490            var oc = new ObservableCollection<ListElement>
 491                         {
 492                             3,
 493                             1,
 494                             4,
 495                             1,
 496                             5,
 497                             9
 498                         };
 499            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 500
 501            obbl.Clear();
 502
 503            Assert.Equal(0, oc.Count);
 504        }
 505
 506        [Fact]
 507        public void Adding_duplicate_item_to_the_binding_list_adds_duplicate_to_the_ObservableCollection()
 508        {
 509            var item = new ListElement(4);
 510            var oc = new ObservableCollection<ListElement>
 511                         {
 512                             3,
 513                             1,
 514                             item,
 515                             1,
 516                             5,
 517                             9
 518                         };
 519            var obbl = new ObservableBackedBindingList<ListElement>(oc);
 520
 521            obbl.Add(item);
 522
 523            Assert.Equal(7, oc.Count);
 524            Assert.Equal(2, oc.Count(i => ReferenceEquals(i, item)));
 525        }
 526
 527        [Fact]
 528        public void Attempt_to_AddNew_for_abstract_type_works_if_AddingNew_event_is_used_to_create_new_object()
 529        {
 530            var obbl = new ObservableBackedBindingList<XNode>(new ObservableCollection<XNode>());
 531            var item = new XText("Some Value");
 532
 533            obbl.AddingNew += (s, e) => e.NewObject = item;
 534            obbl.AddNew();
 535            obbl.EndNew(0);
 536
 537            Assert.True(obbl.Contains(item));
 538        }
 539
 540        [Fact]
 541        public void Attempt_to_AddNew_for_abstract_type_throws_if_AddingNew_event_is_not_used()
 542        {
 543            var obbl = new ObservableBackedBindingList<XNode>(new ObservableCollection<XNode>());
 544
 545            const BindingFlags bindingAttr = BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance;
 546            Assert.Equal(
 547                GenerateException(() => Activator.CreateInstance(typeof(XNode), bindingAttr, null, null, null)).Message,
 548                Assert.Throws<MissingMethodException>(() => obbl.AddNew()).Message);
 549        }
 550
 551        [Fact]
 552        public void Attempt_to_AddNew_for_type_without_parameterless_constructor_works_if_AddingNew_event_is_used_to_create_new_object()
 553        {
 554            var obbl = new ObservableBackedBindingList<XText>(new ObservableCollection<XText>());
 555            var item = new XText("Some Value");
 556
 557            obbl.AddingNew += (s, e) => e.NewObject = item;
 558            obbl.AddNew();
 559            obbl.EndNew(0);
 560
 561            Assert.True(obbl.Contains(item));
 562        }
 563
 564        [Fact]
 565        public void Attempt_to_AddNew_for_type_without_parameterless_constructor_throws_if_AddingNew_event_is_not_used()
 566        {
 567            var obbl = new ObservableBackedBindingList<XText>(new ObservableCollection<XText>());
 568
 569            const BindingFlags bindingAttr = BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance;
 570            Assert.Equal(
 571                GenerateException(() => Activator.CreateInstance(typeof(XText), bindingAttr, null, null, null)).Message,
 572                Assert.Throws<MissingMethodException>(() => obbl.AddNew()).Message);
 573        }
 574
 575        #endregion
 576
 577        #region DbLocalView tests
 578
 579        private Mock<InternalContextForMock> CreateMockedInternalContext(
 580            Mock<IDbSet<FakeEntity>> mockDbSet, IList<FakeEntity> entities = null)
 581        {
 582            entities = entities ?? new List<FakeEntity>();
 583            var mockInternalContext = new Mock<InternalContextForMock>();
 584            mockInternalContext.Setup(i => i.GetLocalEntities<FakeEntity>()).Returns(entities);
 585            mockInternalContext.Setup(i => i.Set<FakeEntity>()).Returns(mockDbSet.Object);
 586            mockInternalContext.Setup(i => i.EntityInContextAndNotDeleted(It.Is<FakeEntity>(e => entities.Contains(e))));
 587            return mockInternalContext;
 588        }
 589
 590        private DbLocalView<FakeEntity> CreateLocalView(Mock<IDbSet<FakeEntity>> mockDbSet, IList<FakeEntity> entities = null)
 591        {
 592            return new DbLocalView<FakeEntity>(CreateMockedInternalContext(mockDbSet, entities).Object);
 593        }
 594
 595        [Fact]
 596        public void DbLocalView_is_initialized_with_entities_from_the_context()
 597        {
 598            var entities = new List<FakeEntity>
 599                               {
 600                                   new FakeEntity(),
 601                                   new FakeEntity()
 602                               };
 603            var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
 604
 605            Assert.Equal(2, localView.Count);
 606            Assert.True(localView.Contains(entities[0]));
 607            Assert.True(localView.Contains(entities[1]));
 608        }
 609
 610        [Fact]
 611        public void Adding_entity_to_DbLocalView_adds_entity_to_DbSet()
 612        {
 613            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 614            var localView = CreateLocalView(mockDbSet);
 615
 616            var entity = new FakeEntity();
 617            localView.Add(entity);
 618
 619            mockDbSet.Verify(s => s.Add(entity), Times.Once());
 620        }
 621
 622        [Fact]
 623        public void Removing_entity_from_DbLocalView_removes_entity_from_DbSet()
 624        {
 625            var entity = new FakeEntity();
 626            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 627            var localView = CreateLocalView(
 628                mockDbSet, new List<FakeEntity>
 629                               {
 630                                   entity
 631                               });
 632
 633            localView.Remove(entity);
 634
 635            mockDbSet.Verify(s => s.Remove(entity), Times.Once());
 636        }
 637
 638        [Fact]
 639        public void Replacing_entity_in_DbLocalView_adds_an_entity_and_removes_an_entity_from_DbSet()
 640        {
 641            var entity = new FakeEntity();
 642            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 643            var localView = CreateLocalView(
 644                mockDbSet, new List<FakeEntity>
 645                               {
 646                                   entity
 647                               });
 648
 649            var newEntity = new FakeEntity();
 650            localView[0] = newEntity;
 651
 652            mockDbSet.Verify(s => s.Remove(entity), Times.Once());
 653            mockDbSet.Verify(s => s.Add(newEntity), Times.Once());
 654        }
 655
 656        [Fact]
 657        public void Moving_an_entity_in_DbLocalView_is_ignored()
 658        {
 659            var entities = new List<FakeEntity>
 660                               {
 661                                   new FakeEntity(),
 662                                   new FakeEntity()
 663                               };
 664            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 665            var localView = CreateLocalView(mockDbSet, entities);
 666
 667            localView.Move(0, 1);
 668
 669            mockDbSet.Verify(s => s.Remove(It.IsAny<FakeEntity>()), Times.Never());
 670            mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
 671        }
 672
 673        [Fact]
 674        public void Adding_entity_to_DbLocalView_that_is_already_in_state_manager_is_ignored()
 675        {
 676            var entity = new FakeEntity();
 677            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 678            var localView = CreateLocalView(
 679                mockDbSet, new List<FakeEntity>
 680                               {
 681                                   entity
 682                               });
 683
 684            localView.Add(entity);
 685
 686            mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
 687        }
 688
 689        [Fact]
 690        public void BindingList_obtained_from_DbLocalView_is_cached()
 691        {
 692            var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>());
 693
 694            var bindingList = localView.BindingList;
 695            Assert.NotNull(bindingList);
 696
 697            var bindingListAgain = localView.BindingList;
 698            Assert.Same(bindingList, bindingListAgain);
 699        }
 700
 701        [Fact]
 702        public void BindingList_obtaibed_from_DbLocalView_stays_in_sync_with_the_local_view()
 703        {
 704            var entities = new List<FakeEntity>
 705                               {
 706                                   new FakeEntity(),
 707                                   new FakeEntity()
 708                               };
 709            var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
 710
 711            var bindingList = localView.BindingList;
 712            Assert.Equal(2, bindingList.Count);
 713
 714            localView.Add(new FakeEntity());
 715            Assert.Equal(3, bindingList.Count);
 716
 717            localView.Remove(entities[0]);
 718            Assert.Equal(2, bindingList.Count);
 719        }
 720
 721        [Fact]
 722        public void DbLocalView_stays_in_sync_with_BindingList_obtaibed_from_it()
 723        {
 724            var entities = new List<FakeEntity>
 725                               {
 726                                   new FakeEntity(),
 727                                   new FakeEntity()
 728                               };
 729            var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
 730
 731            var bindingList = localView.BindingList;
 732            Assert.Equal(2, bindingList.Count);
 733
 734            bindingList.Add(new FakeEntity());
 735            Assert.Equal(3, localView.Count);
 736
 737            bindingList.Remove(entities[0]);
 738            Assert.Equal(2, localView.Count);
 739        }
 740
 741        [Fact]
 742        public void Clear_on_DbLocalView_removes_all_items_from_DbSet()
 743        {
 744            var entities = new List<FakeEntity>
 745                               {
 746                                   new FakeEntity(),
 747                                   new FakeEntity()
 748                               };
 749            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 750            var localView = CreateLocalView(mockDbSet, entities);
 751
 752            localView.Clear();
 753
 754            Assert.Equal(0, localView.Count);
 755            mockDbSet.Verify(s => s.Remove(It.IsAny<FakeEntity>()), Times.Exactly(2));
 756        }
 757
 758        [Fact]
 759        public void Attempted_adds_of_duplicates_to_DbLocalView_are_ignored()
 760        {
 761            var entities = new List<FakeEntity>
 762                               {
 763                                   new FakeEntity()
 764                               };
 765            var mockDbSet = new Mock<IDbSet<FakeEntity>>();
 766            var localView = CreateLocalView(mockDbSet, entities);
 767
 768            localView.Add(entities[0]);
 769
 770            Assert.Equal(1, localView.Count);
 771            mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
 772        }
 773
 774        [Fact]
 775        public void State_manager_Remove_event_causes_entity_to_be_removed_from_DbLocalView()
 776        {
 777            var entity = new FakeEntity();
 778            var mockInternalContext = CreateMockedInternalContext(
 779                new Mock<IDbSet<FakeEntity>>(), new List<FakeEntity>
 780                                                    {
 781                                                        entity
 782                                                    });
 783
 784            CollectionChangeEventHandler stateManagerChanged = null;
 785            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 786                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 787
 788            var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
 789
 790            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, entity));
 791
 792            Assert.False(localView.Contains(entity));
 793        }
 794
 795        [Fact]
 796        public void State_manager_Remove_event_for_entity_not_in_DbLocalView_is_ignored()
 797        {
 798            var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
 799
 800            CollectionChangeEventHandler stateManagerChanged = null;
 801            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 802                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 803
 804            new DbLocalView<FakeEntity>(mockInternalContext.Object);
 805
 806            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, new FakeEntity()));
 807        }
 808
 809        [Fact]
 810        public void State_manager_Remove_event_for_entity_of_wrong_type_for_DbLocalView_is_ignored()
 811        {
 812            var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
 813
 814            CollectionChangeEventHandler stateManagerChanged = null;
 815            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 816                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 817
 818            new DbLocalView<FakeEntity>(mockInternalContext.Object);
 819
 820            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, "Wrong Type"));
 821        }
 822
 823        [Fact]
 824        public void State_manager_Add_event_causes_entity_to_be_added_to_DbLocalView()
 825        {
 826            var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
 827
 828            CollectionChangeEventHandler stateManagerChanged = null;
 829            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 830                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 831
 832            var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
 833
 834            var entity = new FakeEntity();
 835            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, entity));
 836
 837            Assert.True(localView.Contains(entity));
 838        }
 839
 840        [Fact]
 841        public void State_manager_Add_event_for_entity_already_in_DbLocalView_is_ignored()
 842        {
 843            var entity = new FakeEntity();
 844            var mockInternalContext = CreateMockedInternalContext(
 845                new Mock<IDbSet<FakeEntity>>(), new List<FakeEntity>
 846                                                    {
 847                                                        entity
 848                                                    });
 849
 850            CollectionChangeEventHandler stateManagerChanged = null;
 851            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 852                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 853
 854            var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
 855
 856            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, entity));
 857
 858            Assert.Equal(1, localView.Count);
 859        }
 860
 861        [Fact]
 862        public void State_manager_Add_event_for_entity_of_wrong_type_for_DbLocalView_is_ignored()
 863        {
 864            var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
 865
 866            CollectionChangeEventHandler stateManagerChanged = null;
 867            mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
 868                Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
 869
 870            var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
 871
 872            stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, "Wrong Type"));
 873
 874            Assert.Equal(0, localView.Count);
 875        }
 876
 877        #endregion
 878
 879        #region ToBindingList tests
 880
 881        [Fact]
 882        public void ToBindingList_throws_when_given_null_ObservableCollection()
 883        {
 884            Assert.Equal(
 885                "source",
 886                Assert.Throws<ArgumentNullException>(() => ObservableCollectionExtensions.ToBindingList<FakeEntity>(null)).ParamName);
 887        }
 888
 889        [Fact]
 890        public void ToBindingList_returns_the_cached_BindingList_when_called_with_DbLocalView()
 891        {
 892            var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>());
 893
 894            var bindingList = localView.ToBindingList();
 895            Assert.NotNull(bindingList);
 896
 897            var bindingListAgain = localView.ToBindingList();
 898            Assert.Same(bindingList, bindingListAgain);
 899        }
 900
 901        [Fact]
 902        public void ToBindingList_returns_a_new_binding_list_each_time_when_called_on_non_DbLocalView_ObervableCollections()
 903        {
 904            var oc = new ObservableCollection<FakeEntity>();
 905
 906            var bindingList = oc.ToBindingList();
 907            Assert.NotNull(bindingList);
 908
 909            var bindingListAgain = oc.ToBindingList();
 910            Assert.NotNull(bindingListAgain);
 911            Assert.NotSame(bindingList, bindingListAgain);
 912        }
 913
 914        #endregion
 915
 916        #region ObservableListSource tests
 917
 918        [Fact]
 919        public void ObservableListSource_exposes_ObervableCollection_parameterless_constructor()
 920        {
 921            var ols = new ObservableListSource<FakeEntity>();
 922            Assert.Equal(0, ols.Count);
 923        }
 924
 925        [Fact]
 926        public void ObservableListSource_exposes_ObervableCollection_IEnumerable_constructor()
 927        {
 928            IEnumerable<FakeEntity> entities = new[] { new FakeEntity(), new FakeEntity() };
 929            var ols = new ObservableListSource<FakeEntity>(entities);
 930            Assert.Equal(2, ols.Count);
 931        }
 932
 933        [Fact]
 934        public void ObservableListSource_exposes_ObervableCollection_List_constructor()
 935        {
 936            var entities = new List<FakeEntity>
 937                               {
 938                                   new FakeEntity(),
 939                                   new FakeEntity()
 940                               };
 941            var ols = new ObservableListSource<FakeEntity>(entities);
 942            Assert.Equal(2, ols.Count);
 943        }
 944
 945        [Fact]
 946        public void ObservableListSource_ContainsListCollection_returns_false()
 947        {
 948            Assert.False(((IListSource)new ObservableListSource<FakeEntity>()).ContainsListCollection);
 949        }
 950
 951        [Fact]
 952        public void ObservableListSource_GetList_returns_BindingList_attached_to_the_ObservableCollection()
 953        {
 954            var ols = new ObservableListSource<FakeEntity>
 955                          {
 956                              new FakeEntity(),
 957                              new FakeEntity()
 958                          };
 959            var bindingList = ((IListSource)ols).GetList();
 960
 961            Assert.Equal(2, bindingList.Count);
 962
 963            ols.Add(new FakeEntity());
 964            Assert.Equal(3, bindingList.Count);
 965
 966            ols.Remove(ols[0]);
 967            Assert.Equal(2, bindingList.Count);
 968
 969            bindingList.Add(new FakeEntity());
 970            Assert.Equal(3, ols.Count);
 971
 972            bindingList.RemoveAt(0);
 973            Assert.Equal(2, ols.Count);
 974        }
 975
 976        [Fact]
 977        public void The_BindingList_returned_from_ObservableListSource_GetList_is_cached()
 978        {
 979            var ols = new ObservableListSource<FakeEntity>();
 980            var bindingList = ((IListSource)ols).GetList();
 981
 982            Assert.Same(bindingList, ((IListSource)ols).GetList());
 983        }
 984
 985        #endregion
 986
 987        #region DbQuery as IListSource tests
 988
 989        [Fact]
 990        public void DbQuery_ContainsListCollection_returns_false()
 991        {
 992            var fakeQuery = new DbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
 993
 994            Assert.False(((IListSource)fakeQuery).ContainsListCollection);
 995        }
 996
 997        [Fact]
 998        public void Non_generic_DbQuery_ContainsListCollection_returns_false()
 999        {
1000            var fakeQuery = new InternalDbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
1001
1002            Assert.False(((IListSource)fakeQuery).ContainsListCollection);
1003        }
1004
1005        [Fact]
1006        public void DbQuery_GetList_throws_indicating_that_binding_to_queries_is_not_allowed()
1007        {
1008            var fakeQuery = new DbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
1009
1010            Assert.Equal(
1011                Strings.DbQuery_BindingToDbQueryNotSupported,
1012                Assert.Throws<NotSupportedException>(() => ((IListSource)fakeQuery).GetList()).Message);
1013        }
1014
1015        [Fact]
1016        public void Non_generic_DbQuery_GetList_throws_indicating_that_binding_to_queries_is_not_allowed()
1017        {
1018            var fakeQuery = new InternalDbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
1019
1020            Assert.Equal(
1021                Strings.DbQuery_BindingToDbQueryNotSupported,
1022                Assert.Throws<NotSupportedException>(() => ((IListSource)fakeQuery).GetList()).Message);
1023        }
1024
1025        #endregion
1026
1027        #region Load tests
1028
1029        [Fact]
1030        public void Load_throws_when_given_null_query()
1031        {
1032            Assert.Equal("source", Assert.Throws<ArgumentNullException>(() => QueryableExtensions.Load(null)).ParamName);
1033        }
1034
1035        [Fact]
1036        public void Load_enumerates_the_query()
1037        {
1038            var count = 0;
1039            var mockEnumerator = new Mock<IEnumerator<FakeEntity>>();
1040            var mockQuery = new Mock<IList<FakeEntity>>();
1041            mockQuery.Setup(q => q.GetEnumerator()).Returns(mockEnumerator.Object);
1042            mockEnumerator.Setup(e => e.MoveNext()).Returns(() => count++ < 5 ? true : false);
1043
1044            mockQuery.Object.AsQueryable().Load();
1045
1046            mockEnumerator.Verify(e => e.MoveNext(), Times.Exactly(6));
1047        }
1048
1049        #endregion
1050    }
1051}