/test/EntityFramework/UnitTests/DatabindingTests.cs

# · C# · 841 lines · 640 code · 198 blank · 3 comment · 2 complexity · 372c995933e98db6989a99f459a8cf61 MD5 · raw file

  1. namespace ProductivityApiUnitTests
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using System.ComponentModel;
  7. using System.Data.Entity;
  8. using System.Data.Entity.Infrastructure;
  9. using System.Data.Entity.Internal;
  10. using System.Data.Entity.Internal.Linq;
  11. using System.Data.Entity.ModelConfiguration.Internal.UnitTests;
  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. /// <summary>
  19. /// Unit tests for data binding and DbSet.Local.
  20. /// </summary>
  21. public class DatabindingTests : TestBase
  22. {
  23. #region Test subjects
  24. private class ListElement
  25. {
  26. public ListElement()
  27. {
  28. }
  29. public ListElement(int i)
  30. {
  31. Int = i;
  32. NullableInt = i;
  33. String = i.ToString();
  34. XNode = new XText(i.ToString());
  35. Random = new Random();
  36. ByteArray = new byte[] { (byte)i, (byte)i, (byte)i, (byte)i };
  37. }
  38. public static implicit operator ListElement(int i)
  39. {
  40. return new ListElement(i);
  41. }
  42. public int Int { get; set; }
  43. public int? NullableInt { get; set; }
  44. public string String { get; set; }
  45. public XNode XNode { get; set; }
  46. public Random Random { get; set; }
  47. public byte[] ByteArray { get; set; }
  48. public static PropertyDescriptor Property(string name)
  49. {
  50. return TypeDescriptor.GetProperties(typeof(ListElement))[name];
  51. }
  52. }
  53. private class DerivedListElement : ListElement
  54. {
  55. public DerivedListElement()
  56. {
  57. }
  58. public DerivedListElement(int i)
  59. : base(i)
  60. {
  61. }
  62. }
  63. private class ListElementComparer : IEqualityComparer<ListElement>
  64. {
  65. public bool Equals(ListElement x, ListElement y)
  66. {
  67. return x.Int == y.Int;
  68. }
  69. public int GetHashCode(ListElement obj)
  70. {
  71. return obj.Int;
  72. }
  73. }
  74. #endregion
  75. #region SortableBindingList tests
  76. private void SortTest(string property, ListSortDirection direction)
  77. {
  78. var list = new List<ListElement> { 3, 1, 4, 1, 5, 9 };
  79. var sortedList = direction == ListSortDirection.Ascending
  80. ? new List<ListElement> {1, 1, 3, 4, 5, 9}
  81. : new List<ListElement> {9, 5, 4, 3, 1, 1};
  82. var bindingList = new SortableBindingList<ListElement>(list);
  83. ((IBindingList)bindingList).ApplySort(ListElement.Property(property), direction);
  84. Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
  85. }
  86. [Fact]
  87. public void SortableBindingList_can_sort_ascending_using_IComparable_on_value_type()
  88. {
  89. SortTest("Int", ListSortDirection.Ascending);
  90. }
  91. [Fact]
  92. public void SortableBindingList_can_sort_ascending_using_IComparable_on_nullable_value_type()
  93. {
  94. SortTest("NullableInt", ListSortDirection.Ascending);
  95. }
  96. [Fact]
  97. public void SortableBindingList_can_sort_ascending_using_IComparable_on_reference_type()
  98. {
  99. SortTest("String", ListSortDirection.Ascending);
  100. }
  101. [Fact]
  102. public void SortableBindingList_can_sort_descending_using_IComparable_on_value_type()
  103. {
  104. SortTest("Int", ListSortDirection.Descending);
  105. }
  106. [Fact]
  107. public void SortableBindingList_can_sort_descending_using_IComparable_on_nullable_value_type()
  108. {
  109. SortTest("NullableInt", ListSortDirection.Descending);
  110. }
  111. [Fact]
  112. public void SortableBindingList_can_sort_descending_using_IComparable_on_reference_type()
  113. {
  114. SortTest("String", ListSortDirection.Descending);
  115. }
  116. [Fact]
  117. public void SortableBindingList_can_sort_ascending_for_XNode_using_ToString()
  118. {
  119. SortTest("XNode", ListSortDirection.Ascending);
  120. }
  121. [Fact]
  122. public void SortableBindingList_can_sort_descending_for_XNode_using_ToString()
  123. {
  124. SortTest("XNode", ListSortDirection.Descending);
  125. }
  126. [Fact]
  127. public void SortableBindingList_does_not_sort_for_non_XNode_that_does_not_implement_IComparable()
  128. {
  129. var list = new List<ListElement> { 3, 1, 4, 1, 5, 9 };
  130. var unsortedList = new List<ListElement> { 3, 1, 4, 1, 5, 9 };
  131. var bindingList = new SortableBindingList<ListElement>(list);
  132. ((IBindingList)bindingList).ApplySort(ListElement.Property("Random"), ListSortDirection.Ascending);
  133. Assert.True(list.SequenceEqual(unsortedList, new ListElementComparer()));
  134. }
  135. [Fact]
  136. public void SortableBindingList_does_not_sort_for_byte_arrays()
  137. {
  138. var list = new List<ListElement> { 3, 1, 4, 1, 5, 9 };
  139. var unsortedList = new List<ListElement> { 3, 1, 4, 1, 5, 9 };
  140. var bindingList = new SortableBindingList<ListElement>(list);
  141. ((IBindingList)bindingList).ApplySort(ListElement.Property("ByteArray"), ListSortDirection.Descending);
  142. Assert.True(list.SequenceEqual(unsortedList, new ListElementComparer()));
  143. }
  144. [Fact]
  145. public void SortableBindingList_can_sort_when_list_contains_derived_objects()
  146. {
  147. var list = new List<ListElement> { new DerivedListElement(3), new DerivedListElement(1), new DerivedListElement(4) };
  148. var sortedList = new List<ListElement> { new DerivedListElement(1), new DerivedListElement(3), new DerivedListElement(4) };
  149. var bindingList = new SortableBindingList<ListElement>(list);
  150. ((IBindingList)bindingList).ApplySort(ListElement.Property("Int"), ListSortDirection.Ascending);
  151. Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
  152. }
  153. [Fact]
  154. public void SortableBindingList_can_sort_when_list_is_of_derived_type()
  155. {
  156. var list = new List<DerivedListElement> { new DerivedListElement(3), new DerivedListElement(1), new DerivedListElement(4) };
  157. var sortedList = new List<DerivedListElement> { new DerivedListElement(1), new DerivedListElement(3), new DerivedListElement(4) };
  158. var bindingList = new SortableBindingList<DerivedListElement>(list);
  159. ((IBindingList)bindingList).ApplySort(ListElement.Property("Int"), ListSortDirection.Ascending);
  160. Assert.True(list.SequenceEqual(sortedList, new ListElementComparer()));
  161. }
  162. #endregion
  163. #region ObservableBackedBindingList tests
  164. [Fact]
  165. public void Items_added_to_ObservableCollection_are_added_to_binding_list()
  166. {
  167. var oc = new ObservableCollection<ListElement>();
  168. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  169. var item = new ListElement(1);
  170. oc.Add(item);
  171. Assert.True(obbl.Contains(item));
  172. }
  173. [Fact]
  174. public void Items_removed_from_ObservableCollection_are_removed_from_binding_list()
  175. {
  176. var item = new ListElement(4);
  177. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  178. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  179. oc.Remove(item);
  180. Assert.False(obbl.Contains(item));
  181. Assert.Equal(5, obbl.Count);
  182. }
  183. [Fact]
  184. public void Items_replaced_in_the_ObservableCollection_are_replaced_in_the_binding_list()
  185. {
  186. var item = new ListElement(4);
  187. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  188. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  189. var newItem = new ListElement(-4);
  190. oc[2] = newItem;
  191. Assert.False(obbl.Contains(item));
  192. Assert.True(obbl.Contains(newItem));
  193. Assert.Equal(6, obbl.Count);
  194. }
  195. [Fact]
  196. public void Items_cleared_in_the_ObservableCollection_are_cleared_in_the_binding_list()
  197. {
  198. var oc = new ObservableCollection<ListElement> { 3, 1, 4, 1, 5, 9 };
  199. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  200. oc.Clear();
  201. Assert.Equal(0, obbl.Count);
  202. }
  203. [Fact]
  204. public void Adding_duplicate_item_to_the_ObservableCollection_adds_duplicate_to_the_binding_list()
  205. {
  206. var item = new ListElement(4);
  207. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  208. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  209. oc.Add(item);
  210. Assert.Equal(7, obbl.Count);
  211. Assert.Equal(2, obbl.Count(i => ReferenceEquals(i, item)));
  212. }
  213. [Fact]
  214. public void Items_added_to_the_binding_list_are_added_to_the_ObservableCollection()
  215. {
  216. var oc = new ObservableCollection<ListElement>();
  217. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  218. var item = new ListElement(7);
  219. obbl.Add(item);
  220. Assert.True(oc.Contains(item));
  221. }
  222. [Fact]
  223. public void Items_added_to_the_binding_list_with_AddNew_are_added_to_the_ObservableCollection()
  224. {
  225. var oc = new ObservableCollection<ListElement>();
  226. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  227. var item = obbl.AddNew();
  228. obbl.EndNew(0);
  229. Assert.True(oc.Contains(item));
  230. }
  231. [Fact]
  232. public void Items_canceled_during_AddNew_are_not_added_to_the_ObservableCollection()
  233. {
  234. var oc = new ObservableCollection<ListElement>();
  235. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  236. var item = obbl.AddNew();
  237. obbl.CancelNew(0);
  238. Assert.False(oc.Contains(item));
  239. }
  240. [Fact]
  241. public void Items_inserted_into_the_binding_list_are_added_to_the_ObservableCollection()
  242. {
  243. var oc = new ObservableCollection<ListElement>();
  244. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  245. var item = new ListElement(7);
  246. obbl.Insert(0, item);
  247. Assert.True(oc.Contains(item));
  248. }
  249. [Fact]
  250. public void Items_set_in_the_binding_list_are_replaced_in_the_ObservableCollection()
  251. {
  252. var item = new ListElement(4);
  253. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  254. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  255. var newItem = new ListElement(7);
  256. obbl[2] = newItem;
  257. Assert.True(oc.Contains(newItem));
  258. Assert.False(oc.Contains(item));
  259. }
  260. [Fact]
  261. public void Items_removed_from_the_binding_list_are_removed_from_the_ObservableCollection()
  262. {
  263. var item = new ListElement(4);
  264. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  265. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  266. obbl.Remove(item);
  267. Assert.False(oc.Contains(item));
  268. }
  269. [Fact]
  270. public void Items_removed_by_index_from_the_binding_list_are_removed_from_the_ObservableCollection()
  271. {
  272. var item = new ListElement(4);
  273. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  274. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  275. obbl.RemoveAt(2);
  276. Assert.False(oc.Contains(item));
  277. }
  278. [Fact]
  279. public void Items_cleared_from_the_binding_list_are_cleared_from_the_ObservableCollection()
  280. {
  281. var oc = new ObservableCollection<ListElement> { 3, 1, 4, 1, 5, 9 };
  282. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  283. obbl.Clear();
  284. Assert.Equal(0, oc.Count);
  285. }
  286. [Fact]
  287. public void Adding_duplicate_item_to_the_binding_list_adds_duplicate_to_the_ObservableCollection()
  288. {
  289. var item = new ListElement(4);
  290. var oc = new ObservableCollection<ListElement> { 3, 1, item, 1, 5, 9 };
  291. var obbl = new ObservableBackedBindingList<ListElement>(oc);
  292. obbl.Add(item);
  293. Assert.Equal(7, oc.Count);
  294. Assert.Equal(2, oc.Count(i => ReferenceEquals(i, item)));
  295. }
  296. [Fact]
  297. public void Attempt_to_AddNew_for_abstract_type_works_if_AddingNew_event_is_used_to_create_new_object()
  298. {
  299. var obbl = new ObservableBackedBindingList<XNode>(new ObservableCollection<XNode>());
  300. var item = new XText("Some Value");
  301. obbl.AddingNew += (s, e) => e.NewObject = item;
  302. obbl.AddNew();
  303. obbl.EndNew(0);
  304. Assert.True(obbl.Contains(item));
  305. }
  306. [Fact]
  307. public void Attempt_to_AddNew_for_abstract_type_throws_if_AddingNew_event_is_not_used()
  308. {
  309. var obbl = new ObservableBackedBindingList<XNode>(new ObservableCollection<XNode>());
  310. const BindingFlags bindingAttr = BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance;
  311. Assert.Equal(GenerateException(() => Activator.CreateInstance(typeof(XNode), bindingAttr, null, null, null)).Message, Assert.Throws<MissingMethodException>(() => obbl.AddNew()).Message);
  312. }
  313. [Fact]
  314. public void Attempt_to_AddNew_for_type_without_parameterless_constructor_works_if_AddingNew_event_is_used_to_create_new_object()
  315. {
  316. var obbl = new ObservableBackedBindingList<XText>(new ObservableCollection<XText>());
  317. var item = new XText("Some Value");
  318. obbl.AddingNew += (s, e) => e.NewObject = item;
  319. obbl.AddNew();
  320. obbl.EndNew(0);
  321. Assert.True(obbl.Contains(item));
  322. }
  323. [Fact]
  324. public void Attempt_to_AddNew_for_type_without_parameterless_constructor_throws_if_AddingNew_event_is_not_used()
  325. {
  326. var obbl = new ObservableBackedBindingList<XText>(new ObservableCollection<XText>());
  327. const BindingFlags bindingAttr = BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance;
  328. Assert.Equal(GenerateException(() => Activator.CreateInstance(typeof(XText), bindingAttr, null, null, null)).Message, Assert.Throws<MissingMethodException>(() => obbl.AddNew()).Message);
  329. }
  330. #endregion
  331. #region DbLocalView tests
  332. private Mock<InternalContextForMock> CreateMockedInternalContext(Mock<IDbSet<FakeEntity>> mockDbSet, IList<FakeEntity> entities = null)
  333. {
  334. entities = entities ?? new List<FakeEntity>();
  335. var mockInternalContext = new Mock<InternalContextForMock>();
  336. mockInternalContext.Setup(i => i.GetLocalEntities<FakeEntity>()).Returns(entities);
  337. mockInternalContext.Setup(i => i.Set<FakeEntity>()).Returns(mockDbSet.Object);
  338. mockInternalContext.Setup(i => i.EntityInContextAndNotDeleted(It.Is<FakeEntity>(e => entities.Contains(e))));
  339. return mockInternalContext;
  340. }
  341. private DbLocalView<FakeEntity> CreateLocalView(Mock<IDbSet<FakeEntity>> mockDbSet, IList<FakeEntity> entities = null)
  342. {
  343. return new DbLocalView<FakeEntity>(CreateMockedInternalContext(mockDbSet, entities).Object);
  344. }
  345. [Fact]
  346. public void DbLocalView_is_initialized_with_entities_from_the_context()
  347. {
  348. var entities = new List<FakeEntity> { new FakeEntity(), new FakeEntity() };
  349. var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
  350. Assert.Equal(2, localView.Count);
  351. Assert.True(localView.Contains(entities[0]));
  352. Assert.True(localView.Contains(entities[1]));
  353. }
  354. [Fact]
  355. public void Adding_entity_to_DbLocalView_adds_entity_to_DbSet()
  356. {
  357. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  358. var localView = CreateLocalView(mockDbSet);
  359. var entity = new FakeEntity();
  360. localView.Add(entity);
  361. mockDbSet.Verify(s => s.Add(entity), Times.Once());
  362. }
  363. [Fact]
  364. public void Removing_entity_from_DbLocalView_removes_entity_from_DbSet()
  365. {
  366. var entity = new FakeEntity();
  367. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  368. var localView = CreateLocalView(mockDbSet, new List<FakeEntity> {entity});
  369. localView.Remove(entity);
  370. mockDbSet.Verify(s => s.Remove(entity), Times.Once());
  371. }
  372. [Fact]
  373. public void Replacing_entity_in_DbLocalView_adds_an_entity_and_removes_an_entity_from_DbSet()
  374. {
  375. var entity = new FakeEntity();
  376. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  377. var localView = CreateLocalView(mockDbSet, new List<FakeEntity> { entity });
  378. var newEntity = new FakeEntity();
  379. localView[0] = newEntity;
  380. mockDbSet.Verify(s => s.Remove(entity), Times.Once());
  381. mockDbSet.Verify(s => s.Add(newEntity), Times.Once());
  382. }
  383. [Fact]
  384. public void Moving_an_entity_in_DbLocalView_is_ignored()
  385. {
  386. var entities = new List<FakeEntity> {new FakeEntity(), new FakeEntity()};
  387. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  388. var localView = CreateLocalView(mockDbSet, entities);
  389. localView.Move(0, 1);
  390. mockDbSet.Verify(s => s.Remove(It.IsAny<FakeEntity>()), Times.Never());
  391. mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
  392. }
  393. [Fact]
  394. public void Adding_entity_to_DbLocalView_that_is_already_in_state_manager_is_ignored()
  395. {
  396. var entity = new FakeEntity();
  397. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  398. var localView = CreateLocalView(mockDbSet, new List<FakeEntity> { entity });
  399. localView.Add(entity);
  400. mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
  401. }
  402. [Fact]
  403. public void BindingList_obtained_from_DbLocalView_is_cached()
  404. {
  405. var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>());
  406. var bindingList = localView.BindingList;
  407. Assert.NotNull(bindingList);
  408. var bindingListAgain = localView.BindingList;
  409. Assert.Same(bindingList, bindingListAgain);
  410. }
  411. [Fact]
  412. public void BindingList_obtaibed_from_DbLocalView_stays_in_sync_with_the_local_view()
  413. {
  414. var entities = new List<FakeEntity> { new FakeEntity(), new FakeEntity() };
  415. var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
  416. var bindingList = localView.BindingList;
  417. Assert.Equal(2, bindingList.Count);
  418. localView.Add(new FakeEntity());
  419. Assert.Equal(3, bindingList.Count);
  420. localView.Remove(entities[0]);
  421. Assert.Equal(2, bindingList.Count);
  422. }
  423. [Fact]
  424. public void DbLocalView_stays_in_sync_with_BindingList_obtaibed_from_it()
  425. {
  426. var entities = new List<FakeEntity> { new FakeEntity(), new FakeEntity() };
  427. var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>(), entities);
  428. var bindingList = localView.BindingList;
  429. Assert.Equal(2, bindingList.Count);
  430. bindingList.Add(new FakeEntity());
  431. Assert.Equal(3, localView.Count);
  432. bindingList.Remove(entities[0]);
  433. Assert.Equal(2, localView.Count);
  434. }
  435. [Fact]
  436. public void Clear_on_DbLocalView_removes_all_items_from_DbSet()
  437. {
  438. var entities = new List<FakeEntity> { new FakeEntity(), new FakeEntity() };
  439. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  440. var localView = CreateLocalView(mockDbSet, entities);
  441. localView.Clear();
  442. Assert.Equal(0, localView.Count);
  443. mockDbSet.Verify(s => s.Remove(It.IsAny<FakeEntity>()), Times.Exactly(2));
  444. }
  445. [Fact]
  446. public void Attempted_adds_of_duplicates_to_DbLocalView_are_ignored()
  447. {
  448. var entities = new List<FakeEntity> { new FakeEntity() };
  449. var mockDbSet = new Mock<IDbSet<FakeEntity>>();
  450. var localView = CreateLocalView(mockDbSet, entities);
  451. localView.Add(entities[0]);
  452. Assert.Equal(1, localView.Count);
  453. mockDbSet.Verify(s => s.Add(It.IsAny<FakeEntity>()), Times.Never());
  454. }
  455. [Fact]
  456. public void State_manager_Remove_event_causes_entity_to_be_removed_from_DbLocalView()
  457. {
  458. var entity = new FakeEntity();
  459. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>(), new List<FakeEntity> { entity });
  460. CollectionChangeEventHandler stateManagerChanged = null;
  461. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  462. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  463. var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
  464. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, entity));
  465. Assert.False(localView.Contains(entity));
  466. }
  467. [Fact]
  468. public void State_manager_Remove_event_for_entity_not_in_DbLocalView_is_ignored()
  469. {
  470. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
  471. CollectionChangeEventHandler stateManagerChanged = null;
  472. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  473. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  474. new DbLocalView<FakeEntity>(mockInternalContext.Object);
  475. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, new FakeEntity()));
  476. }
  477. [Fact]
  478. public void State_manager_Remove_event_for_entity_of_wrong_type_for_DbLocalView_is_ignored()
  479. {
  480. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
  481. CollectionChangeEventHandler stateManagerChanged = null;
  482. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  483. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  484. new DbLocalView<FakeEntity>(mockInternalContext.Object);
  485. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Remove, "Wrong Type"));
  486. }
  487. [Fact]
  488. public void State_manager_Add_event_causes_entity_to_be_added_to_DbLocalView()
  489. {
  490. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
  491. CollectionChangeEventHandler stateManagerChanged = null;
  492. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  493. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  494. var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
  495. var entity = new FakeEntity();
  496. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, entity));
  497. Assert.True(localView.Contains(entity));
  498. }
  499. [Fact]
  500. public void State_manager_Add_event_for_entity_already_in_DbLocalView_is_ignored()
  501. {
  502. var entity = new FakeEntity();
  503. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>(), new List<FakeEntity> { entity });
  504. CollectionChangeEventHandler stateManagerChanged = null;
  505. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  506. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  507. var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
  508. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, entity));
  509. Assert.Equal(1, localView.Count);
  510. }
  511. [Fact]
  512. public void State_manager_Add_event_for_entity_of_wrong_type_for_DbLocalView_is_ignored()
  513. {
  514. var mockInternalContext = CreateMockedInternalContext(new Mock<IDbSet<FakeEntity>>());
  515. CollectionChangeEventHandler stateManagerChanged = null;
  516. mockInternalContext.Setup(i => i.RegisterObjectStateManagerChangedEvent(It.IsAny<CollectionChangeEventHandler>())).
  517. Callback<CollectionChangeEventHandler>(h => stateManagerChanged = h);
  518. var localView = new DbLocalView<FakeEntity>(mockInternalContext.Object);
  519. stateManagerChanged.Invoke(null, new CollectionChangeEventArgs(CollectionChangeAction.Add, "Wrong Type"));
  520. Assert.Equal(0, localView.Count);
  521. }
  522. #endregion
  523. #region ToBindingList tests
  524. [Fact]
  525. public void ToBindingList_throws_when_given_null_ObservableCollection()
  526. {
  527. Assert.Equal("source", Assert.Throws<ArgumentNullException>(() => ObservableCollectionExtensions.ToBindingList<FakeEntity>(null)).ParamName);
  528. }
  529. [Fact]
  530. public void ToBindingList_returns_the_cached_BindingList_when_called_with_DbLocalView()
  531. {
  532. var localView = CreateLocalView(new Mock<IDbSet<FakeEntity>>());
  533. var bindingList = localView.ToBindingList();
  534. Assert.NotNull(bindingList);
  535. var bindingListAgain = localView.ToBindingList();
  536. Assert.Same(bindingList, bindingListAgain);
  537. }
  538. [Fact]
  539. public void ToBindingList_returns_a_new_binding_list_each_time_when_called_on_non_DbLocalView_ObervableCollections()
  540. {
  541. var oc = new ObservableCollection<FakeEntity>();
  542. var bindingList = oc.ToBindingList();
  543. Assert.NotNull(bindingList);
  544. var bindingListAgain = oc.ToBindingList();
  545. Assert.NotNull(bindingListAgain);
  546. Assert.NotSame(bindingList, bindingListAgain);
  547. }
  548. #endregion
  549. #region ObservableListSource tests
  550. [Fact]
  551. public void ObservableListSource_exposes_ObervableCollection_parameterless_constructor()
  552. {
  553. var ols = new ObservableListSource<FakeEntity>();
  554. Assert.Equal(0, ols.Count);
  555. }
  556. [Fact]
  557. public void ObservableListSource_exposes_ObervableCollection_IEnumerable_constructor()
  558. {
  559. IEnumerable<FakeEntity> entities = new[] {new FakeEntity(), new FakeEntity()};
  560. var ols = new ObservableListSource<FakeEntity>(entities);
  561. Assert.Equal(2, ols.Count);
  562. }
  563. [Fact]
  564. public void ObservableListSource_exposes_ObervableCollection_List_constructor()
  565. {
  566. var entities = new List<FakeEntity> { new FakeEntity(), new FakeEntity() };
  567. var ols = new ObservableListSource<FakeEntity>(entities);
  568. Assert.Equal(2, ols.Count);
  569. }
  570. [Fact]
  571. public void ObservableListSource_ContainsListCollection_returns_false()
  572. {
  573. Assert.False(((IListSource)new ObservableListSource<FakeEntity>()).ContainsListCollection);
  574. }
  575. [Fact]
  576. public void ObservableListSource_GetList_returns_BindingList_attached_to_the_ObservableCollection()
  577. {
  578. var ols = new ObservableListSource<FakeEntity> { new FakeEntity(), new FakeEntity() };
  579. var bindingList = ((IListSource) ols).GetList();
  580. Assert.Equal(2, bindingList.Count);
  581. ols.Add(new FakeEntity());
  582. Assert.Equal(3, bindingList.Count);
  583. ols.Remove(ols[0]);
  584. Assert.Equal(2, bindingList.Count);
  585. bindingList.Add(new FakeEntity());
  586. Assert.Equal(3, ols.Count);
  587. bindingList.RemoveAt(0);
  588. Assert.Equal(2, ols.Count);
  589. }
  590. [Fact]
  591. public void The_BindingList_returned_from_ObservableListSource_GetList_is_cached()
  592. {
  593. var ols = new ObservableListSource<FakeEntity>();
  594. var bindingList = ((IListSource)ols).GetList();
  595. Assert.Same(bindingList, ((IListSource)ols).GetList());
  596. }
  597. #endregion
  598. #region DbQuery as IListSource tests
  599. [Fact]
  600. public void DbQuery_ContainsListCollection_returns_false()
  601. {
  602. var fakeQuery = new DbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
  603. Assert.False(((IListSource)fakeQuery).ContainsListCollection);
  604. }
  605. [Fact]
  606. public void Non_generic_DbQuery_ContainsListCollection_returns_false()
  607. {
  608. var fakeQuery = new InternalDbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
  609. Assert.False(((IListSource)fakeQuery).ContainsListCollection);
  610. }
  611. [Fact]
  612. public void DbQuery_GetList_throws_indicating_that_binding_to_queries_is_not_allowed()
  613. {
  614. var fakeQuery = new DbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
  615. Assert.Equal(Strings.DbQuery_BindingToDbQueryNotSupported, Assert.Throws<NotSupportedException>(() => ((IListSource)fakeQuery).GetList()).Message);
  616. }
  617. [Fact]
  618. public void Non_generic_DbQuery_GetList_throws_indicating_that_binding_to_queries_is_not_allowed()
  619. {
  620. var fakeQuery = new InternalDbQuery<FakeEntity>(new Mock<IInternalQuery<FakeEntity>>().Object);
  621. Assert.Equal(Strings.DbQuery_BindingToDbQueryNotSupported, Assert.Throws<NotSupportedException>(() => ((IListSource)fakeQuery).GetList()).Message);
  622. }
  623. #endregion
  624. #region Load tests
  625. [Fact]
  626. public void Load_throws_when_given_null_query()
  627. {
  628. Assert.Equal("source", Assert.Throws<ArgumentNullException>(() => IQueryableExtensions.Load(null)).ParamName);
  629. }
  630. [Fact]
  631. public void Load_enumerates_the_query()
  632. {
  633. int count = 0;
  634. var mockEnumerator = new Mock<IEnumerator<FakeEntity>>();
  635. var mockQuery = new Mock<IList<FakeEntity>>();
  636. mockQuery.Setup(q => q.GetEnumerator()).Returns(mockEnumerator.Object);
  637. mockEnumerator.Setup(e => e.MoveNext()).Returns(() => count++ < 5 ? true : false);
  638. mockQuery.Object.AsQueryable().Load();
  639. mockEnumerator.Verify(e => e.MoveNext(), Times.Exactly(6));
  640. }
  641. #endregion
  642. }
  643. }