PageRenderTime 25ms CodeModel.GetById 11ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/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//===================================================================================
 17using System;
 18using System.Collections.Generic;
 19using System.Xml.Linq;
 20using Microsoft.VisualStudio.TestTools.UnitTesting;
 21using StockTraderRI.Infrastructure;
 22using StockTraderRI.Modules.Market.Services;
 23using StockTraderRI.Modules.Market.Tests.Mocks;
 24using StockTraderRI.Modules.Market.Tests.Properties;
 25
 26namespace StockTraderRI.Modules.Market.Tests.Services
 27{
 28    [TestClass]
 29    public class MarketFeedServiceFixture
 30    {
 31        [TestMethod]
 32        public void CanGetPriceAndVolumeFromMarketFeed()
 33        {
 34            using (var marketFeed = new TestableMarketFeedService(new MockPriceUpdatedEventAggregator()))
 35            {
 36                marketFeed.TestUpdatePrice("STOCK0", 40.00m, 1234);
 37
 38                Assert.AreEqual<decimal>(40.00m, marketFeed.GetPrice("STOCK0"));
 39                Assert.AreEqual<long>(1234, marketFeed.GetVolume("STOCK0"));
 40            }
 41        }
 42
 43        [TestMethod]
 44        public void ShouldPublishUpdatedOnSinglePriceChange()
 45        {
 46            var eventAggregator = new MockPriceUpdatedEventAggregator();
 47
 48            using (TestableMarketFeedService marketFeed = new TestableMarketFeedService(eventAggregator))
 49            {
 50                marketFeed.TestUpdatePrice("STOCK0", 30.00m, 1000);
 51            }
 52
 53            Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
 54        }
 55
 56        [TestMethod]
 57        public void GetPriceOfNonExistingSymbolThrows()
 58        {
 59            using (var marketFeed = new MarketFeedService(new MockPriceUpdatedEventAggregator()))
 60            {
 61                try
 62                {
 63                    marketFeed.GetPrice("NONEXISTANT");
 64                    Assert.Fail("No exception thrown");
 65                }
 66                catch (Exception ex)
 67                {
 68                    Assert.IsInstanceOfType(ex, typeof(ArgumentException));
 69                    Assert.IsTrue(ex.Message.Contains("Symbol does not exist in market feed."));
 70                }
 71            }
 72        }
 73
 74        [TestMethod]
 75        public void SymbolExistsWorksAsExpected()
 76        {
 77            using (var marketFeed = new MarketFeedService(new MockPriceUpdatedEventAggregator()))
 78            {
 79                Assert.IsTrue(marketFeed.SymbolExists("STOCK0"));
 80                Assert.IsFalse(marketFeed.SymbolExists("NONEXISTANT"));
 81            }
 82        }
 83
 84        [TestMethod]
 85        public void ShouldUpdatePricesWithin5Points()
 86        {
 87            using (var marketFeed = new TestableMarketFeedService(new MockPriceUpdatedEventAggregator()))
 88            {
 89                decimal originalPrice = marketFeed.GetPrice("STOCK0");
 90                marketFeed.InvokeUpdatePrices();
 91                Assert.IsTrue(Math.Abs(marketFeed.GetPrice("STOCK0") - originalPrice) <= 5);
 92            }
 93        }
 94
 95        [TestMethod]
 96        public void ShouldPublishUpdatedAfterUpdatingPrices()
 97        {
 98            var eventAggregator = new MockPriceUpdatedEventAggregator();
 99
100            using (var marketFeed = new TestableMarketFeedService(eventAggregator))
101            {
102                marketFeed.InvokeUpdatePrices();
103            }
104            Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
105        }
106
107
108        [TestMethod]
109        public void MarketServiceReadsIntervalFromXml()
110        {
111            var xmlMarketData = XDocument.Parse(Resources.TestXmlMarketData);
112            using (var marketFeed = new TestableMarketFeedService(xmlMarketData, new MockPriceUpdatedEventAggregator()))
113            {
114                Assert.AreEqual<int>(5000, marketFeed.RefreshInterval);
115            }
116        }
117
118        [TestMethod]
119        public void UpdateShouldPublishWithinRefreshInterval()
120        {
121            var eventAggregator = new MockPriceUpdatedEventAggregator();
122
123            using (var marketFeed = new TestableMarketFeedService(eventAggregator))
124            {
125                marketFeed.RefreshInterval = 500; // ms
126
127                var callCompletedEvent = new System.Threading.ManualResetEvent(false);
128
129                eventAggregator.MockMarketPriceUpdatedEvent.PublishCalledEvent +=
130                        delegate { callCompletedEvent.Set(); };
131#if SILVERLIGHT
132                callCompletedEvent.WaitOne(5000); // Wait up to 5 seconds
133#else
134                callCompletedEvent.WaitOne(5000, true); // Wait up to 5 seconds
135#endif
136            }
137            Assert.IsTrue(eventAggregator.MockMarketPriceUpdatedEvent.PublishCalled);
138        }
139
140        [TestMethod]
141        public void RefreshIntervalDefaultsTo10SecondsWhenNotSpecified()
142        {
143            var xmlMarketData = XDocument.Parse(Resources.TestXmlMarketData);
144            xmlMarketData.Element("MarketItems").Attribute("RefreshRate").Remove();
145
146            using (var marketFeed = new TestableMarketFeedService(xmlMarketData, new MockPriceUpdatedEventAggregator()))
147            {
148                Assert.AreEqual<int>(10000, marketFeed.RefreshInterval);
149            }
150        }
151
152        [TestMethod]
153        public void PublishedEventContainsTheUpdatedPriceList()
154        {
155            var eventAgregator = new MockPriceUpdatedEventAggregator();
156            var marketFeed = new TestableMarketFeedService(eventAgregator);
157            Assert.IsTrue(marketFeed.SymbolExists("STOCK0"));
158
159            marketFeed.InvokeUpdatePrices();
160
161            Assert.IsTrue(eventAgregator.MockMarketPriceUpdatedEvent.PublishCalled);
162            var payload = eventAgregator.MockMarketPriceUpdatedEvent.PublishArgumentPayload;
163            Assert.IsNotNull(payload);
164            Assert.IsTrue(payload.ContainsKey("STOCK0"));
165            Assert.AreEqual(marketFeed.GetPrice("STOCK0"), payload["STOCK0"]);
166        }
167
168    }
169
170    class TestableMarketFeedService : MarketFeedService
171    {
172        public TestableMarketFeedService(MockPriceUpdatedEventAggregator eventAggregator)
173            : base(eventAggregator)
174        {
175
176        }
177
178        public TestableMarketFeedService(XDocument xmlDocument, MockPriceUpdatedEventAggregator eventAggregator)
179            : base(xmlDocument, eventAggregator)
180        {
181        }
182
183        public void TestUpdatePrice(string tickerSymbol, decimal price, long volume)
184        {
185            this.UpdatePrice(tickerSymbol, price, volume);
186        }
187
188        public void InvokeUpdatePrices()
189        {
190            base.UpdatePrices();
191        }
192    }
193
194
195
196    class MockPriceUpdatedEventAggregator : MockEventAggregator
197    {
198        public MockMarketPricesUpdatedEvent MockMarketPriceUpdatedEvent = new MockMarketPricesUpdatedEvent();
199        public MockPriceUpdatedEventAggregator()
200        {
201            AddMapping<MarketPricesUpdatedEvent>(MockMarketPriceUpdatedEvent);
202        }
203
204        public class MockMarketPricesUpdatedEvent : MarketPricesUpdatedEvent
205        {
206            public bool PublishCalled;
207            public IDictionary<string, decimal> PublishArgumentPayload;
208            public EventHandler PublishCalledEvent;
209
210            private void OnPublishCalledEvent(object sender, EventArgs args)
211            {
212                if (PublishCalledEvent != null)
213                    PublishCalledEvent(sender, args);
214            }
215
216            public override void Publish(IDictionary<string, decimal> payload)
217            {
218                PublishCalled = true;
219                PublishArgumentPayload = payload;
220                OnPublishCalledEvent(this, EventArgs.Empty);
221            }
222        }
223    }
224}