Its a Boy !!!
The due date is December 29th.
1: [Test]
2: public void MyTest1()
3: {
4: string expectedXml = "<Order></Order>";
5: string actualXml = "<Order></Order>";
6:
7: DynamicMock mockObject = new DynamicMock(typeof(IOrderManager));
8: mockObject.Expect("SubmitOrder", new IsEquivalentXml(expectedXml));
9: ClassUnderTest classUnderTest =
10: new ClassUnderTest((IOrderManager)mockObject.MockInstance);
11: classUnderTest.DoSometing(actualXml);
12: mockObject.Verify();
13: }
1: [Test]
2: public void MyTest2()
3: {
4: string expectedXml = "<Order/>";
5: string actualXml = "<Order></Order>";
6:
7: DynamicMock mockObject = new DynamicMock(typeof(IOrderManager));
8: mockObject.Expect("SubmitOrder", new IsEquivalentXml(expectedXml));
9: ClassUnderTest classUnderTest =
10: new ClassUnderTest((IOrderManager)mockObject.MockInstance);
11: classUnderTest.DoSometing(actualXml);
12: mockObject.Verify();
13: }
1: [Test]
2: public void MyTest3()
3: {
4: string expectedXml = @"<Order id=""123""></Order>";
5: string actualXml = "<Order id='123'></Order>";
6:
7: DynamicMock mockObject = new DynamicMock(typeof(IOrderManager));
8: mockObject.Expect("SubmitOrder", new IsEquivalentXml(expectedXml));
9: ClassUnderTest classUnderTest =
10: new ClassUnderTest((IOrderManager)mockObject.MockInstance);
11: classUnderTest.DoSometing(actualXml);
12: mockObject.Verify();
13: }
1: [Test]
2: public void MyTest10()
3: {
4: string expectedXml = @"<Order>abc123</Order>";
5: string actualXml = "<Order> abc123 </Order>";
6:
7: DynamicMock mockObject = new DynamicMock(typeof(IOrderManager));
8: mockObject.Expect("SubmitOrder",
9: new IsEquivalentXml(expectedXml, XmlDiffOptions.IgnoreWhitespace));
10: ClassUnderTest classUnderTest =
11: new ClassUnderTest((IOrderManager)mockObject.MockInstance);
12: classUnderTest.DoSometing(actualXml);
13: mockObject.Verify();
14: }
1: using System;
2:
3: namespace CustomNMockConstraintsClassLibrary
4: {
5: public class ClassUnderTest
6: {
7: IOrderManager _orderManager;
8:
9: public ClassUnderTest(IOrderManager orderManager)
10: {
11: this._orderManager = orderManager;
12: }
13:
14: public void DoSometing(string orderXml)
15: {
16: this._orderManager.SubmitOrder(orderXml);
17: }
18: }
19: }
The actual Constraint class is shown below. Notice that I inherit from the NMock BaseConstraint class instead of the IConstraint interface. BaseConstraint is an abstract class that already implements the IConstraint interface.
1: using System;
2: using System.IO;
3: using System.Xml;
4:
5: using NMock;
6: using NMock.Constraints;
7:
8: using Microsoft.XmlDiffPatch;
9:
10: namespace CustomNMockConstraintsClassLibrary
11: {
12: public class IsEquivalentXml : BaseConstraint
13: {
14: private string _expectedXml = string.Empty;
15: private XmlDiff _xmlDiff = new XmlDiff();
16:
17: public IsEquivalentXml(string xml) : this(xml, XmlDiffOptions.None)
18: {
19: }
20:
21: public IsEquivalentXml(string expectedXml, XmlDiffOptions options)
22: {
23: _expectedXml = expectedXml;
24: _xmlDiff.Options = options;
25: }
26:
27: public override bool Eval(object val)
28: {
29: string actualXml = (string)ExtractActualValue(val);
30: return AreEqual(_expectedXml, actualXml);
31: }
32:
33: public override string Message
34: {
35: get { return "<" + _expectedXml + ">"; }
36: }
37:
38: private bool AreEqual(string expectedXml, string actualXml)
39: {
40: bool areEqual = false;
41:
42: try
43: {
44: areEqual = _xmlDiff.Compare(
45: new XmlTextReader(new StringReader(expectedXml)),
46: new XmlTextReader(new StringReader(actualXml)));
47: }
48: catch(Exception e)
49: {
50: _expectedXml += "\n" + e.ToString();
51: }
52:
53: return areEqual;
54: }
55: }
56: }
1: using System;
2: using System.Configuration;
3: using System.Diagnostics;
4: using System.IO;
5: using System.Web;
6: using System.Web.Services.Protocols;
7:
8: namespace CacheExtensionProj
9: {
10: [AttributeUsage(AttributeTargets.Method)]
11: public class CacheExtensionAttribute : SoapExtensionAttribute
12: {
13: private string cacheDurationConfigKey;
14: private int priority;
15:
16: public override Type ExtensionType
17: {
18: get { return typeof(CacheExtension); }
19: }
20:
21: public override int Priority
22: {
23: get { return priority; }
24: set { priority = value; }
25: }
26:
27: public string CacheDurationConfigKey
28: {
29: get { return cacheDurationConfigKey;}
30: set { cacheDurationConfigKey = value;}
31: }
32: }
33:
34: public class CacheExtension : SoapExtension
35: {
36: Stream originalStream;
37: Stream newStream;
38: string cacheKey = null;
39: string cacheDurationConfigKey;
40: int cacheDuration = 0;
41:
42: public override object GetInitializer(LogicalMethodInfo methodInfo,
43: SoapExtensionAttribute attribute)
44: {
45: //Cast attribute and return attribute value
46: CacheExtensionAttribute cea = (CacheExtensionAttribute)attribute;
47: return cea.CacheDurationConfigKey;
48: }
49:
50: public override object GetInitializer(Type serviceType)
51: {
52: return null;
53: }
54:
55: public override void Initialize(object initializer)
56: {
57: cacheDurationConfigKey = (string)initializer;
58: if (cacheDurationConfigKey == null
59: cacheDurationConfigKey == string.Empty)
60: {
61: cacheDurationConfigKey = "DefaultCacheDuration";
62: }
63:
64: cacheDuration = GetCacheDuration(cacheDurationConfigKey);
65: }
66:
67: public override void ProcessMessage(SoapMessage message)
68: {
69: switch (message.Stage)
70: {
71: case SoapMessageStage.BeforeSerialize:
72: break;
73:
74: case SoapMessageStage.AfterSerialize:
75: newStream.Position = 0; //need to reset stream
76: CopyStream(newStream, originalStream);
77:
78: SaveStreamToCache(cacheKey, newStream);
79: break;
80:
81: case SoapMessageStage.BeforeDeserialize:
82: //Cache key is the entire request xml string
83: cacheKey = GenerateCacheKeyFromStream(originalStream);
84:
85: Stream stream = GetStreamFromCache(cacheKey);
86: if (stream != null)
87: {
88: Trace.WriteLine("Returning Cached Version");
89: HttpContext.Current.Response.ContentType =
90: "text/xml";
91: CopyStream(stream,
92: HttpContext.Current.Response.OutputStream);
93: HttpContext.Current.Response.Flush();
94: HttpContext.Current.Response.End();
95: }
96: else
97: {
98: CopyStream(originalStream, newStream);
99: newStream.Position = 0; //need to reset stream
100: }
101: break;
102:
103: case SoapMessageStage.AfterDeserialize:
104: break;
105:
106: default:
107: throw new Exception("invalid stage");
108: }
109: }
110:
111: public override Stream ChainStream( Stream stream )
112: {
113: originalStream = stream;
114: newStream = new MemoryStream();
115: return newStream;
116: }
117:
118: private void CopyStream(Stream from, Stream to)
119: {
120: TextReader reader = new StreamReader(from);
121: TextWriter writer = new StreamWriter(to);
122: writer.WriteLine(reader.ReadToEnd());
123: writer.Flush();
124: }
125:
126: private string GenerateCacheKeyFromStream(Stream stream)
127: {
128: string cacheKey = new StreamReader(stream).ReadToEnd();
129: stream.Position = 0; //need to reset stream
130: return cacheKey;
131: }
132:
133: private void SaveStreamToCache(string cacheKey, Stream stream)
134: {
135: if (cacheDuration > 0)
136: {
137: Trace.WriteLine("Saving result in Cache");
138: Trace.WriteLine("cacheKey = " + cacheKey);
139:
140: MemoryStream ms = new MemoryStream();
141: stream.Position = 0;
142: CopyStream(stream, ms);
143: ms.Position = 0;
144:
145: HttpContext.Current.Cache.Insert(cacheKey, ms, null,
146: DateTime.Now.AddHours((double)cacheDuration),
147: TimeSpan.Zero);
148: }
149: }
150:
151: private Stream GetStreamFromCache(string cacheKey)
152: {
153: Stream stream = HttpContext.Current.Cache[cacheKey] as Stream;
154: if (stream != null)
155: {
156: stream.Position = 0;
157: }
158: return stream;
159: }
160:
161: private int GetCacheDuration(string cacheDurationConfigKey)
162: {
163: int cacheDurationValue = -1;
164: string cacheDurationStringValue =
165: ConfigurationSettings.AppSettings[cacheDurationConfigKey];
166: if (cacheDurationStringValue != null &&
167: cacheDurationStringValue != string.Empty)
168: {
169: try
170: {
171: cacheDurationValue = int.Parse(cacheDurationStringValue);
172: if (cacheDurationValue <=0)
173: {
174: Trace.WriteLine("Caching disabled. " +
175: cacheDurationConfigKey +
176: " must be positive and greater than zero.");
177: }
178: }
179: catch(Exception e)
180: {
181: Trace.WriteLine("Caching disabled. Unable to convert " +
182: cacheDurationConfigKey +
183: " value from configuration file into int type. \nException: "
184: + e.ToString());
185: }
186: }
187: else
188: {
189: Trace.WriteLine("Caching disabled. " +
190: cacheDurationConfigKey +
191: " value is null or empty string.");
192: }
193:
194: return cacheDurationValue;
195: }
196: }
197: }
1: [WebMethod]
2: [CacheExtension(CacheDurationConfigKey="GetDateTime.CacheDuration")]
3: public string GetDateTime(string name)
4: {
5: return "Hello " + name + " the time is " + DateTime.Now.ToString();
6: }
1: <appSettings>
2: <add key="DefaultCacheDuration" value="8"/>
3: <add key="GetDateTime.CacheDuration" value="2"/>
4: </appSettings>
1: http://msdn.microsoft.com/msdnmag/issues/04/03/ASPColumn/
2: http://www.theserverside.net/tt/articles/showarticle.tss?id=SOAPExtensions
3: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp03222001.asp
4: http://www.codeguru.com/columns/experts/article.php/c5479/
5: http://www.mastercsharp.com/article.aspx?ArticleID=86&&TopicID=7