In the last post, I simulated an asynchronous call to WCF, by setting custom code behavior on the Begin and End. But that’s not enough. I want to make that even shorter and readable. And even ready for more generic use.
I’m taking advantage of the fact that for a specific synchronous call in WCF, the generated async proxies have a constant signature. I want to write this in my test code:
1 2 |
<span style="color: #000000;">myHandle= WCFAsyncWrapper.AsyncCallOf(() => fakeSourceListProvider.GetSourceList(<span class="kwrd">null</span>))</span> <span style="color: #000000;"> .WillReturn(<span class="str">"Fake Result"</span>, 500);</span> |
This is a wrapper method, that does what I did before, only reads better, and takes as a parameter the synchronous version of the method, and its WillReturn clause takes two arguments: The fake result I want to return from the server, and the timeout I want to simulate.
True magic indeed. Let’s start. Here’s the WCFAsyncWrapper class:
1 2 3 4 5 6 7 |
<span style="color: #000000;"><span class="kwrd">public</span> <span class="kwrd">class</span> WCFAsyncWrapper</span> <span style="color: #000000;">{</span> <span style="color: #000000;"> <span class="kwrd">public</span> <span class="kwrd">static</span> IAsyncReturnValueHandler<T> AsyncCallOf<T>(Expression<Func<T>> syncFunction)</span> <span style="color: #000000;"> {</span> <span style="color: #000000;"> <span class="kwrd">return</span> <span class="kwrd">new</span> AsyncReturnValueHandler<T>(syncFunction);</span> <span style="color: #000000;"> }</span> <span style="color: #000000;">}</span> |
Brilliant, I know. Note that the parameter received is an Expression, not a delegate (as is the default in Isolator APIs). There’s a reason for that – I want to parse the expression for setting behavior on it.
Let’s continue. The AsyncReturnValueHandler class does all the work. Its constructor does the Expression parsing:
1 2 3 4 5 6 7 8 |
<span style="color: #000000;"><span class="kwrd">public</span> AsyncReturnValueHandler(Expression<Func<T>> syncFunction)</span> <span style="color: #000000;">{</span> <span class="rem" style="color: #000000;"> // Parse the expression</span> <span style="color: #000000;"> <span class="kwrd">string</span> name = ((MethodCallExpression) syncFunction.Body).Method.Name;</span> <span style="color: #000000;"> beginName = <span class="str">"Begin"</span> + name;</span> <span style="color: #000000;"> endName = <span class="str">"End"</span> + name;</span> <span style="color: #000000;"> instance = GetInstanceFromExpressionTree(syncFunction);</span> <span style="color: #000000;">}</span> |
The GetInstanceFromExpression method is interesting: It extracts the instance on which the method is invoked. It’s a real reference to the object:
1 2 3 4 5 6 7 |
<span style="color: #000000;"><span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">object</span> GetInstanceFromExpressionTree<T>(Expression<Func<T>> function)</span> <span style="color: #000000;">{</span> <span style="color: #000000;"> var method = function.Body <span class="kwrd">as</span> MethodCallExpression;</span> <span style="color: #000000;"> var source = method.Object <span class="kwrd">as</span> MemberExpression;</span> <span style="color: #000000;"> var constant = source.Expression <span class="kwrd">as</span> ConstantExpression;</span> <span style="color: #000000;"> <span class="kwrd">return</span> (source.Member <span class="kwrd">as</span> System.Reflection.FieldInfo).GetValue(constant.Value);</span> <span style="color: #000000;">}</span> |
A bit of reflection magic. Let’s continue. Now, let’s look at what we return:
1 2 3 4 5 6 7 8 |
<span style="color: #000000;"><span class="kwrd">public</span> IAsyncResult WillReturn(T <span class="kwrd">value</span>, <span class="kwrd">int</span> afterTime)</span> <span style="color: #000000;">{</span> <span style="color: #000000;"> returnValue = <span class="kwrd">value</span>;</span> <span style="color: #000000;"> timeout = afterTime;</span> <span style="color: #000000;"> SetBehavior();</span> <span style="color: #000000;"> <span class="kwrd">return</span> returnedHandle;</span> <span style="color: #000000;">}</span> |
Looks harmless enough. And obviously, SetBehavior is where we set the behavior, similar as before. But this time, I’m using the NonPublic API, which allow me to work with strings as method names. Which is convenient, because I just parsed the synchronous method from the expression, and got me 2 method names for Begin and End. I’m using them with DoInstead and WillReturn respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span style="color: #000000;"><span class="kwrd">private</span> <span class="kwrd">void</span> SetBehavior()</span> <span style="color: #000000;">{</span> <span style="color: #000000;"> Isolate.NonPublic.WhenCalled(instance, <strong>beginName</strong>)</span> <span style="color: #000000;"> .DoInstead((Func<MethodCallContext,<span class="kwrd">object</span>>)( (c) =></span> <span style="color: #000000;"> {</span> <span style="color: #000000;"> WCFAsynchTests.AsyncProcessor dr = d =></span> <span style="color: #000000;"> {</span> <span style="color: #000000;"> Thread.Sleep(timeout);</span> <span style="color: #000000;"> d.DynamicInvoke(returnedHandle);</span> <span style="color: #000000;"> };</span> <span style="color: #000000;"> returnedHandle = dr.BeginInvoke(c.Parameters[1] <span class="kwrd">as</span> Delegate,<span class="kwrd">null</span>, c.Instance);</span> <span style="color: #000000;"> <span class="kwrd">return</span> returnedHandle;</span> <span style="color: #000000;"> }));</span> <span style="color: #000000;"> Isolate.NonPublic.WhenCalled(instance, <strong>endName</strong>).WillReturn(returnValue);</span> <span style="color: #000000;">}</span> |
That’s enough to pass my test, which looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span style="color: #000000;">[Isolated]</span> <span style="color: #000000;">[TestMethod]</span> <span style="color: #000000;"><span class="kwrd">public</span> <span class="kwrd">void</span> WaitingOnFakeAsyncOperation_ToComplete()</span> <span style="color: #000000;">{</span> <span style="color: #000000;"> myHandle= WCFAsyncWrapper.AsyncCallOf(() => fakeSourceListProvider.GetSourceList(<span class="kwrd">null</span>))</span> <span style="color: #000000;"> .WillReturn(<span class="str">"Fake Result"</span>, 500);</span> <span style="color: #000000;"> DataProviderClient client = <span class="kwrd">new</span> DataProviderClient();</span> <span style="color: #000000;"> myHandle = client.GetSourceListFromServerAsync(<span class="str">"<xml></xml>"</span>);</span> <span style="color: #000000;"> <span class="kwrd">while</span> (!myHandle.IsCompleted)</span> <span style="color: #000000;"> {</span> <span style="color: #000000;"> Console.WriteLine(<span class="str">"Waiting..."</span>);</span> <span style="color: #000000;"> Thread.Sleep(100);</span> <span style="color: #000000;"> }</span> <span style="color: #000000;"> Assert.AreEqual(<span class="str">"Fake Result"</span>, client.SourceList);</span> <span style="color: #000000;">}</span> |
Let’s look back and see what we did:
- Built a wrapper that takes the sync method signature, the expected return value and the expected timeout
- Parsed the expression for later use with the NonPublic WhenCalled.
- Set the behavior for the Begin and End method
- Continue with the Act and Assert part of the test.
You can download the sources for this example from here.
PS: Is that cool or is that COOL?
Want to start unit testing? Take advantage of our 15-day FREE trial of Isolator Complete. Get it now.