PageRenderTime 34ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/Framework/src/Ncqrs.Tests/Domain/AggregateRootTests.cs

https://github.com/elfrostie/ncqrs
C# | 317 lines | 245 code | 72 blank | 0 comment | 0 complexity | de7697de1439fbc3ceec201bf40cc4d3 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using FluentAssertions;
  5. using Ncqrs.Domain;
  6. using Ncqrs.Eventing;
  7. using Ncqrs.Eventing.Sourcing;
  8. using Ncqrs.Spec;
  9. using Rhino.Mocks;
  10. using NUnit.Framework;
  11. namespace Ncqrs.Tests.Domain
  12. {
  13. [TestFixture]
  14. public class AggregateRootTests
  15. {
  16. public class HandledEvent
  17. {
  18. }
  19. public class UnhandledEvent
  20. {}
  21. public class MyAggregateRoot : AggregateRoot
  22. {
  23. private readonly List<UncommittedEvent> _uncomittedEvents = new List<UncommittedEvent>();
  24. public int FooEventHandlerInvokeCount = 0;
  25. public MyAggregateRoot()
  26. {
  27. RegisterHandler(new TypeThresholdedActionBasedDomainEventHandler(OnFoo, typeof(HandledEvent), "", false));
  28. }
  29. public MyAggregateRoot(Guid id) : base(id)
  30. {
  31. RegisterHandler(new TypeThresholdedActionBasedDomainEventHandler(OnFoo, typeof(HandledEvent), "", false));
  32. }
  33. public void MethodThatCausesAnEventThatHasAHandler()
  34. {
  35. var e = new HandledEvent();
  36. ApplyEvent(e);
  37. }
  38. public void MethodThatCausesAnEventThatDoesNotConaintAHandler()
  39. {
  40. var e = new UnhandledEvent();
  41. ApplyEvent(e);
  42. }
  43. private void OnFoo(object e)
  44. {
  45. FooEventHandlerInvokeCount++;
  46. }
  47. protected override void OnEventApplied(UncommittedEvent appliedEvent)
  48. {
  49. base.OnEventApplied(appliedEvent);
  50. _uncomittedEvents.Add(appliedEvent);
  51. }
  52. public IEnumerable<UncommittedEvent> GetUncommittedEvents()
  53. {
  54. return _uncomittedEvents;
  55. }
  56. }
  57. [Test]
  58. public void It_should_initialize_with_a_new_id_given_by_the_generator_from_the_environment()
  59. {
  60. var generator = MockRepository.GenerateMock<IUniqueIdentifierGenerator>();
  61. NcqrsEnvironment.SetDefault<IUniqueIdentifierGenerator>(generator);
  62. var theAggregate = new MyAggregateRoot();
  63. generator.AssertWasCalled(g => g.GenerateNewId());
  64. }
  65. [Test]
  66. public void It_should_initialize_with_no_uncommited_events()
  67. {
  68. var theAggregate = new MyAggregateRoot();
  69. theAggregate.GetUncommittedEvents().Count().Should().Be(0);
  70. }
  71. [Test]
  72. public void It_should_initialize_with_version_0()
  73. {
  74. var theAggregate = new MyAggregateRoot();
  75. theAggregate.Version.Should().Be(0);
  76. }
  77. [Test]
  78. public void Applying_an_event_should_at_it_to_the_uncommited_events()
  79. {
  80. var theAggregate = new MyAggregateRoot();
  81. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  82. theAggregate.GetUncommittedEvents().Count().Should().Be(1);
  83. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  84. theAggregate.GetUncommittedEvents().Count().Should().Be(2);
  85. }
  86. [Test]
  87. public void Applying_an_event_when_there_is_no_unit_of_work_should_not_cause_an_exception()
  88. {
  89. var theAggregate = new MyAggregateRoot();
  90. Action act = ()=>theAggregate.MethodThatCausesAnEventThatHasAHandler();
  91. act.ShouldNotThrow();
  92. }
  93. [Test]
  94. public void Applying_an_event_with_no_handler_should_cause_an_exception()
  95. {
  96. var theAggregate = new MyAggregateRoot();
  97. Action act = theAggregate.MethodThatCausesAnEventThatDoesNotConaintAHandler;
  98. act.ShouldThrow<EventNotHandledException>();
  99. }
  100. [Test]
  101. public void Loading_it_from_history_should_apply_all_events()
  102. {
  103. var aggId = Guid.NewGuid();
  104. var stream = Prepare.Events(new HandledEvent(), new HandledEvent(), new HandledEvent()).ForSource(aggId);
  105. var theAggregate = new MyAggregateRoot(aggId);
  106. theAggregate.InitializeFromHistory(stream);
  107. theAggregate.FooEventHandlerInvokeCount.Should().Be(3);
  108. }
  109. [Test]
  110. public void Accepting_the_changes_should_set_the_initial_version_to_the_new_version()
  111. {
  112. var theAggregate = new MyAggregateRoot();
  113. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  114. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  115. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  116. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  117. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  118. theAggregate.InitialVersion.Should().Be(0);
  119. theAggregate.AcceptChanges();
  120. theAggregate.InitialVersion.Should().Be(5);
  121. }
  122. [Test]
  123. public void Applying_an_event_should_not_effect_the_initial_version()
  124. {
  125. var theAggregate = new MyAggregateRoot();
  126. theAggregate.InitialVersion.Should().Be(0);
  127. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  128. theAggregate.InitialVersion.Should().Be(0);
  129. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  130. theAggregate.InitialVersion.Should().Be(0);
  131. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  132. }
  133. [Test]
  134. public void Applying_an_event_should_affect_the_version()
  135. {
  136. var theAggregate = new MyAggregateRoot();
  137. theAggregate.Version.Should().Be(0);
  138. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  139. theAggregate.Version.Should().Be(1);
  140. theAggregate.GetUncommittedEvents().Last().EventSequence.Should().Be(1);
  141. theAggregate.GetUncommittedEvents().Last().InitialVersionOfEventSource.Should().Be(0);
  142. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  143. theAggregate.Version.Should().Be(2);
  144. theAggregate.GetUncommittedEvents().Last().EventSequence.Should().Be(2);
  145. theAggregate.GetUncommittedEvents().Last().InitialVersionOfEventSource.Should().Be(0);
  146. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  147. }
  148. [Test]
  149. public void Initializing_from_history_should_throw_an_exception_when_the_history_was_null()
  150. {
  151. var theAggregate = new MyAggregateRoot();
  152. Action act = () => theAggregate.InitializeFromHistory(null);
  153. act.ShouldThrow<ArgumentNullException>();
  154. }
  155. [Test]
  156. public void Initializing_from_history_should_not_throw_an_exception_when_the_history_was_empty()
  157. {
  158. var theAggregate = new MyAggregateRoot();
  159. var history = new CommittedEventStream(Guid.Empty);
  160. theAggregate.InitializeFromHistory(history);
  161. }
  162. [Test]
  163. public void Initiazling_from_wrong_history_with_wrong_sequence_should_throw_exception()
  164. {
  165. var theAggregate = new MyAggregateRoot();
  166. const long wrongSequence = 3;
  167. var stream = new CommittedEventStream(theAggregate.EventSourceId,
  168. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, wrongSequence, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)));
  169. Action act = ()=> theAggregate.InitializeFromHistory(stream);
  170. act.ShouldThrow<InvalidOperationException>().And.Message.Should().Contain("sequence");
  171. }
  172. [Test]
  173. public void Initiazling_from_history_with_correct_sequence_should_not_throw_exception()
  174. {
  175. var theAggregate = new MyAggregateRoot();
  176. var stream = new CommittedEventStream(theAggregate.EventSourceId,
  177. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, 1, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)),
  178. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, 2, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)),
  179. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, 3, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)),
  180. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, 4, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)),
  181. new CommittedEvent(Guid.NewGuid(), Guid.NewGuid(), theAggregate.EventSourceId, 5, DateTime.UtcNow, new HandledEvent(), new Version(1, 0)));
  182. theAggregate.InitializeFromHistory(stream);
  183. }
  184. [Test]
  185. public void It_could_not_be_loaded_from_history_when_it_already_contains_uncommitted_events()
  186. {
  187. var theAggregate = new MyAggregateRoot();
  188. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  189. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  190. var stream = Prepare.Events(new HandledEvent(), new HandledEvent()).ForSource(theAggregate.EventSourceId);
  191. Action act = () => theAggregate.InitializeFromHistory(stream);
  192. act.ShouldThrow<InvalidOperationException>();
  193. }
  194. [Test]
  195. public void Constructing_it_with_an_id_should_set_that_to_EventSourceId_property()
  196. {
  197. var theId = Guid.NewGuid();
  198. var theAggregate = new MyAggregateRoot(theId);
  199. theAggregate.EventSourceId.Should().Be(theId);
  200. }
  201. [Test]
  202. public void Applying_an_event_should_call_the_event_handler_only_once()
  203. {
  204. var theAggregate = new MyAggregateRoot();
  205. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  206. theAggregate.FooEventHandlerInvokeCount.Should().Be(1);
  207. }
  208. [Test]
  209. public void Applying_an_event_to_an_agg_root_with_history_should_call_the_event_handler_only_once()
  210. {
  211. var theAggregate = new MyAggregateRoot();
  212. Guid commandId = Guid.NewGuid();
  213. var event1 = new CommittedEvent(commandId, Guid.NewGuid(), theAggregate.EventSourceId, 1, DateTime.UtcNow, new HandledEvent(), new Version(1, 0));
  214. var event2 = new CommittedEvent(commandId, Guid.NewGuid(), theAggregate.EventSourceId, 2, DateTime.UtcNow, new HandledEvent(), new Version(1, 0));
  215. var event3 = new CommittedEvent(commandId, Guid.NewGuid(), theAggregate.EventSourceId, 3, DateTime.UtcNow, new HandledEvent(), new Version(1, 0));
  216. var event4 = new CommittedEvent(commandId, Guid.NewGuid(), theAggregate.EventSourceId, 4, DateTime.UtcNow, new HandledEvent(), new Version(1, 0));
  217. var event5 = new CommittedEvent(commandId, Guid.NewGuid(), theAggregate.EventSourceId, 5, DateTime.UtcNow, new HandledEvent(), new Version(1, 0));
  218. IEnumerable<CommittedEvent> history = new[] { event1, event2, event3, event4, event5 };
  219. ((IEventSource)theAggregate).InitializeFromHistory(new CommittedEventStream(theAggregate.EventSourceId, history));
  220. var eventHandlerCountAfterInitialization = theAggregate.FooEventHandlerInvokeCount;
  221. theAggregate.MethodThatCausesAnEventThatHasAHandler();
  222. theAggregate.FooEventHandlerInvokeCount.Should().Be(eventHandlerCountAfterInitialization + 1);
  223. }
  224. [Test]
  225. public void Should_be_able_to_register_RegisterThreadStaticEventAppliedCallbacks_from_parallel_threads()
  226. {
  227. Action<AggregateRoot, UncommittedEvent> callback = (x, y) => { };
  228. Action registerOneCallbackOnAggregateRoot = () => AggregateRoot.RegisterThreadStaticEventAppliedCallback(callback);
  229. Action registerTwoCallbacksOnAggregateRoot = () =>
  230. {
  231. AggregateRoot.RegisterThreadStaticEventAppliedCallback(callback);
  232. AggregateRoot.RegisterThreadStaticEventAppliedCallback(callback);
  233. };
  234. System.Threading.Tasks.Parallel.Invoke(
  235. registerOneCallbackOnAggregateRoot,
  236. registerTwoCallbacksOnAggregateRoot,
  237. registerOneCallbackOnAggregateRoot,
  238. registerTwoCallbacksOnAggregateRoot,
  239. registerOneCallbackOnAggregateRoot,
  240. registerTwoCallbacksOnAggregateRoot,
  241. registerOneCallbackOnAggregateRoot,
  242. registerTwoCallbacksOnAggregateRoot);
  243. }
  244. }
  245. }