/V2.2/trunk/RI/Desktop/StockTraderRI.Modules.Market.Tests/Services/MarketFeedServiceFixture.cs

# · C# · 224 lines · 175 code · 33 blank · 16 comment · 2 complexity · cacd39d7314dc422b5f06acd7c7cdafc MD5 · raw file

  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4. //===================================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===================================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===================================================================================
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Xml.Linq;
  20. using Microsoft.VisualStudio.TestTools.UnitTesting;
  21. using StockTraderRI.Infrastructure;
  22. using StockTraderRI.Modules.Market.Services;
  23. using StockTraderRI.Modules.Market.Tests.Mocks;
  24. using StockTraderRI.Modules.Market.Tests.Properties;
  25. namespace StockTraderRI.Modules.Market.Tests.Services
  26. {
  27. [TestClass]
  28. public class MarketFeedServiceFixture
  29. {
  30. [TestMethod]
  31. public void CanGetPriceAndVolumeFromMarketFeed()
  32. {
  33. using (var marketFeed = new TestableMarketFeedService(new MockPriceUpdatedEventAggregator()))
  34. {
  35. marketFeed.TestUpdatePrice("STOCK0", 40.00m, 1234);
  36. Assert.AreEqual<decimal>(40.00m, marketFeed.GetPrice("STOCK0"));
  37. Assert.AreEqual<long>(1234, marketFeed.GetVolume("STOCK0"));
  38. }
  39. }
  40. [TestMethod]
  41. public void ShouldPublishUpdatedOnSinglePriceChange()
  42. {
  43. var eventAggregator = new MockPriceUpdatedEventAggregator();
  44. using (TestableMarketFeedService marketFeed = new TestableMarketFeedService(eventAggregator))
  45. {
  46. marketFeed.TestUpdatePrice("STOCK0", 30.00m, 1000);
  47. }
  48. Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
  49. }
  50. [TestMethod]
  51. public void GetPriceOfNonExistingSymbolThrows()
  52. {
  53. using (var marketFeed = new MarketFeedService(new MockPriceUpdatedEventAggregator()))
  54. {
  55. try
  56. {
  57. marketFeed.GetPrice("NONEXISTANT");
  58. Assert.Fail("No exception thrown");
  59. }
  60. catch (Exception ex)
  61. {
  62. Assert.IsInstanceOfType(ex, typeof(ArgumentException));
  63. Assert.IsTrue(ex.Message.Contains("Symbol does not exist in market feed."));
  64. }
  65. }
  66. }
  67. [TestMethod]
  68. public void SymbolExistsWorksAsExpected()
  69. {
  70. using (var marketFeed = new MarketFeedService(new MockPriceUpdatedEventAggregator()))
  71. {
  72. Assert.IsTrue(marketFeed.SymbolExists("STOCK0"));
  73. Assert.IsFalse(marketFeed.SymbolExists("NONEXISTANT"));
  74. }
  75. }
  76. [TestMethod]
  77. public void ShouldUpdatePricesWithin5Points()
  78. {
  79. using (var marketFeed = new TestableMarketFeedService(new MockPriceUpdatedEventAggregator()))
  80. {
  81. decimal originalPrice = marketFeed.GetPrice("STOCK0");
  82. marketFeed.InvokeUpdatePrices();
  83. Assert.IsTrue(Math.Abs(marketFeed.GetPrice("STOCK0") - originalPrice) <= 5);
  84. }
  85. }
  86. [TestMethod]
  87. public void ShouldPublishUpdatedAfterUpdatingPrices()
  88. {
  89. var eventAggregator = new MockPriceUpdatedEventAggregator();
  90. using (var marketFeed = new TestableMarketFeedService(eventAggregator))
  91. {
  92. marketFeed.InvokeUpdatePrices();
  93. }
  94. Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
  95. }
  96. [TestMethod]
  97. public void MarketServiceReadsIntervalFromXml()
  98. {
  99. var xmlMarketData = XDocument.Parse(Resources.TestXmlMarketData);
  100. using (var marketFeed = new TestableMarketFeedService(xmlMarketData, new MockPriceUpdatedEventAggregator()))
  101. {
  102. Assert.AreEqual<int>(5000, marketFeed.RefreshInterval);
  103. }
  104. }
  105. [TestMethod]
  106. public void UpdateShouldPublishWithinRefreshInterval()
  107. {
  108. var eventAggregator = new MockPriceUpdatedEventAggregator();
  109. using (var marketFeed = new TestableMarketFeedService(eventAggregator))
  110. {
  111. marketFeed.RefreshInterval = 500; // ms
  112. var callCompletedEvent = new System.Threading.ManualResetEvent(false);
  113. eventAggregator.MockMarketPriceUpdatedEvent.PublishCalledEvent +=
  114. delegate { callCompletedEvent.Set(); };
  115. #if SILVERLIGHT
  116. callCompletedEvent.WaitOne(5000); // Wait up to 5 seconds
  117. #else
  118. callCompletedEvent.WaitOne(5000, true); // Wait up to 5 seconds
  119. #endif
  120. }
  121. Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
  122. }
  123. [TestMethod]
  124. public void RefreshIntervalDefaultsTo10SecondsWhenNotSpecified()
  125. {
  126. var xmlMarketData = XDocument.Parse(Resources.TestXmlMarketData);
  127. xmlMarketData.Element("MarketItems").Attribute("RefreshRate").Remove();
  128. using (var marketFeed = new TestableMarketFeedService(xmlMarketData, new MockPriceUpdatedEventAggregator()))
  129. {
  130. Assert.AreEqual<int>(10000, marketFeed.RefreshInterval);
  131. }
  132. }
  133. [TestMethod]
  134. public void PublishedEventContainsTheUpdatedPriceList()
  135. {
  136. var eventAgregator = new MockPriceUpdatedEventAggregator();
  137. var marketFeed = new TestableMarketFeedService(eventAgregator);
  138. Assert.IsTrue(marketFeed.SymbolExists("STOCK0"));
  139. marketFeed.InvokeUpdatePrices();
  140. Assert.IsTrue(eventAgregator.MockMarketPriceUpdatedEvent.PublishCalled);
  141. var payload = eventAgregator.MockMarketPriceUpdatedEvent.PublishArgumentPayload;
  142. Assert.IsNotNull(payload);
  143. Assert.IsTrue(payload.ContainsKey("STOCK0"));
  144. Assert.AreEqual(marketFeed.GetPrice("STOCK0"), payload["STOCK0"]);
  145. }
  146. }
  147. class TestableMarketFeedService : MarketFeedService
  148. {
  149. public TestableMarketFeedService(MockPriceUpdatedEventAggregator eventAggregator)
  150. : base(eventAggregator)
  151. {
  152. }
  153. public TestableMarketFeedService(XDocument xmlDocument, MockPriceUpdatedEventAggregator eventAggregator)
  154. : base(xmlDocument, eventAggregator)
  155. {
  156. }
  157. public void TestUpdatePrice(string tickerSymbol, decimal price, long volume)
  158. {
  159. this.UpdatePrice(tickerSymbol, price, volume);
  160. }
  161. public void InvokeUpdatePrices()
  162. {
  163. base.UpdatePrices();
  164. }
  165. }
  166. class MockPriceUpdatedEventAggregator : MockEventAggregator
  167. {
  168. public MockMarketPricesUpdatedEvent MockMarketPriceUpdatedEvent = new MockMarketPricesUpdatedEvent();
  169. public MockPriceUpdatedEventAggregator()
  170. {
  171. AddMapping<MarketPricesUpdatedEvent>(MockMarketPriceUpdatedEvent);
  172. }
  173. public class MockMarketPricesUpdatedEvent : MarketPricesUpdatedEvent
  174. {
  175. public bool PublishCalled;
  176. public IDictionary<string, decimal> PublishArgumentPayload;
  177. public EventHandler PublishCalledEvent;
  178. private void OnPublishCalledEvent(object sender, EventArgs args)
  179. {
  180. if (PublishCalledEvent != null)
  181. PublishCalledEvent(sender, args);
  182. }
  183. public override void Publish(IDictionary<string, decimal> payload)
  184. {
  185. PublishCalled = true;
  186. PublishArgumentPayload = payload;
  187. OnPublishCalledEvent(this, EventArgs.Empty);
  188. }
  189. }
  190. }
  191. }