Brad has just blogged that “Mocking Still Not Quite There For Me“. I looked at his post and thought that this can serve as a good example for using a Custom Checker so here goes:
(Ill post only the test code itself the full working example can be downloaded here)
1 |
[TestClass]<br /><span class="kwrd">public</span> <span class="kwrd">class</span> CustomChecker<br />{<br /> <span class="rem">// Just an empty method</span><br /> <span class="kwrd">public</span> <span class="kwrd">void</span> VoidEmptyMethod()<br /> {<br /> }<br /><br /> <span class="rem">// Our custom Checker</span><br /> <span class="kwrd">public</span> <span class="kwrd">bool</span> Check(ParameterCheckerEventArgs args)<br /> {<br /> MethodInfo actual = (args.ArgumentValue <span class="kwrd">as</span> MethodInfoWrapper).Method;<br /> MethodInfo expected = GetType().GetMethod(<span class="str">"VoidEmptyMethod"</span>);<br /> <span class="kwrd">return</span> actual == expected;<br /> }<br /><br /> [TestMethod,VerifyMocks]<br /> <span class="kwrd">public</span> <span class="kwrd">void</span> CustomCheckerTest()<br /> {<br /> <span class="rem">//Create a stub of ITestClassCommand (stubClassCmd) </span><br /> ITestClassCommand stubClassCmd =<br /> RecorderManager.CreateMockedObject<ITestClassCommand>();<br /> <span class="rem">//Create a stub of ITestCommand (stubTestCmd) </span><br /> ITestCommand stubTestCmd = RecorderManager.CreateMockedObject<ITestCommand>();<br /> <span class="rem">//Get the MethodInfo for an empty, void-returning method (methInfo)</span><br /> List<ITestCommand> fakeList = <span class="kwrd">new</span> List<ITestCommand>();<br /> fakeList.Add(stubTestCmd);<br /> <span class="kwrd">using</span> (RecordExpectations rec = <span class="kwrd">new</span> RecordExpectations())<br /> {<br /> <span class="rem">//- In response to ShouldCreateInstance, return true</span><br /> <span class="kwrd">bool</span> dummy = stubTestCmd.ShouldCreateInstance;<br /> rec.Return(<span class="kwrd">true</span>);<br /> <span class="rem">//- In response to EnumerateTestCommands, return StubTestCmd</span><br /> IEnumerable<ITestCommand> dummy2 = stubClassCmd.EnumerateTestCommands(<span class="kwrd">null</span>);<br /> rec.Return(fakeList).CheckArguments(<span class="kwrd">new</span> ParameterCheckerEx(Check));<br /> }<br /> <span class="rem">//Act: Call TestCommandFactory.Make, passing stubClassCmd and methInfo</span><br /> TestCommandFactory.Make(stubClassCmd, GetType().GetMethod(<span class="str">"VoidEmptyMethod"</span>));<br /> <span class="rem">//Assert:Ensure that the IMethodInfo passed </span><br /> <span class="rem">//into stubClassCmd.EnumerateTestMethod wrapped methInfo</span><br /> <span class="rem">// - this is done by the ParameterCheckerEx</span><br /> <br /> <br /> <span class="rem">//Ensure that we returned a wrapped ITestCommand </span><br /> <span class="rem">//(test all the levels of wrapping described above)</span><br /> <span class="rem">// - here can other assertion follow</span><br /> }<br />} |
And the point is the usage of “ParameterCheckerEx”, Using this mechanism one can extend the argument checking mechanism to do almost anything. in our case we checked that the argument passed during the run is the wrapped VoidEmptyMethod MethodInfo.
Last tip. Inside the Check method one can access the “args.ExpectedValue” property that will store the expected value passed during the recording of the call. In our case the null passed here:
1 |
IEnumerable<ITestCommand> dummy2 = stubClassCmd.EnumerateTestCommands(<span class="kwrd">null</span>); |
That said I do agree that there are cases in which Manual Mocks are more appropriate. In my experience this is usually true to a more simpler kind of scenarios, in which the overhead of using a framework is higher then just writing down the manual mocks. However, time and time again i have seen how quickly those Manual Mocks become a small mini framework, which in my opinion will always be the lesser solution to a full grown mature framework.