PageRenderTime 44ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/test/EntityFramework/UnitTests/DatabindingTests.cs

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