Guest post by Lior Friedman. This is a part of a series called “Back to basics” of unit testing.
One of the best things about the Isolator is that it can fake instances which are created inside the production code. This kind of faking is called "faking a future instance".
Lets see an example how this can be used. Here’s my production code that I need to test:
1 |
<span style="color: blue">public class </span><span style="color: #2b91af">Client<br /></span>{<br /> <span style="color: #2b91af">Server </span>m_Server = <span style="color: blue">null</span>;<br /><br /> <span style="color: blue">public </span>Client(<span style="color: #2b91af">IPAddress </span>addr)<br /> {<br /> m_Server = <span style="color: blue">new </span><span style="color: #2b91af">Server</span>();<br /> m_Server.Connect(addr);<br /> }<br /><br /> <span style="color: blue">public int </span>SendInfo(<span style="color: blue">string </span>message)<br /> {<br /> m_Server.Send(message);<br /> <span style="color: blue">string </span>answer = m_Server.Recieve();<br /> <span style="color: blue">if </span>(answer != <span style="color: #a31515">"OK"</span>)<br /> {<br /> <span style="color: blue">throw new </span><span style="color: #2b91af">ApplicationException<br /> </span>(<span style="color: #a31515">"Failed To Communicate"</span>);<br /> }<br /> <span style="color: blue">return </span>message.Length;<br /> }<br />} |
The method I want to test is SendInfo, and a simple test would be to make sure that when sending is successful, the actual number bytes sent is returned by it.
The tricky bit resides in the Constructor of the Client class . As you can see, the client creates his own server and connect to it based on the address given by the user.
Here’s the test code:
1 |
[<span style="color: #2b91af">TestMethod</span>()]<br /><span style="color: blue">public void </span>SendInfo_SuccesfulSend_SendsAllBytes()<br />{<br /> <span style="color: green">//creating the fake<br /> </span><span style="color: #2b91af">Server </span>fakeServer = <span style="color: #2b91af">Isolate</span>.Fake.Instance<<span style="color: #2b91af">Server</span>>();<br /> <span style="color: green">//setting behavior<br /> </span><span style="color: #2b91af">Isolate</span>.WhenCalled(() => fakeServer.Recieve()).<br /> WillReturn(<span style="color: #a31515">"OK"</span>);<br /> <span style="color: green">//When the next Server is created, swap it with fakeServer<br /> </span><span style="color: #2b91af">Isolate</span>.Swap.NextInstance<<span style="color: #2b91af">Server</span>>().With(fakeServer);<br /> <br /> <span style="color: blue">var </span>address = <span style="color: blue">new </span><span style="color: #2b91af">IPAddress</span>( <br /> <span style="color: blue">new byte</span>[] {192,168,0,9}<br /> );<br /> <span style="color: blue">string </span>message = <span style="color: #a31515">"Hello Server"</span>;<br /><br /> <span style="color: #2b91af">Client </span>target = <span style="color: blue">new </span><span style="color: #2b91af">Client</span>(address);<br /> <span style="color: blue">int </span>actual = target.SendInfo(message);<br /><br /> <span style="color: #2b91af">Assert</span>.AreEqual(message.Length, actual);<br />} |
Specifically important is this line:
1 |
<span style="color: green">//When the next Server is created, swap it with fakeServer</span> |
1 |
<span style="color: green"></span><span style="color: #2b91af">Isolate</span>.Swap.NextInstance<<span style="color: #2b91af">Server</span>>().With(fakeServer); |
After I’ve created the fakeServer and set the desired behavior, this command tells Isolator to swap the next created instance with the fakeServer I’ve created. That is, the next time someone will will create an instance of the Server Class (as done in the client constructor), Instead of getting a real server he will get the fake instance I specified in the "With" segment.
By the way, in the “With” clause, I can supply a fake or a real object. Quite simple isn’t it?