Friday, August 15, 2008

[Rhino] Mock Anomalies: SetupResult.For to Lambda - "No Dice"

I had probably jumped to some conclusions with my earlier post.  While it's true GenerateStub<T>() refuses to accomodate SetupResult, the below testcase passes:

[TestMethod]
public void GenerateStubAndSetupResult()
{
    //With GenerateStub() alone, SetupResult fails with
    //IDemo stub = (IDemo)MockRepository.GenerateStub<IDemo>();
    IDemo stub = new MockRepository().Stub<IDemo>();
 
    int j = 0;
 
    SetupResult
        .For<string>(stub.ReturnStringNoArgs())
        .Do((Func<string>)(() => { return (++j).ToString(); }));
 
    SetupResult
        .For<string>(stub.ReturnStringWithInt32Arg(300)).IgnoreArguments()
        .Do((Func<int, string>)((arg) => { return string.Format("000{0}", arg); }));
 
    stub.Replay();
    Assert.AreEqual("1", stub.ReturnStringNoArgs());
    Assert.AreEqual("2", stub.ReturnStringNoArgs());
    Assert.AreEqual("000400", stub.ReturnStringWithInt32Arg(400));
    Assert.AreEqual("000500", stub.ReturnStringWithInt32Arg(500));
} 

Let's take our previous code and rewrite it, using the lesson above:

[TestMethod]

public void TestSetupStubOnceCallMultipleTimes2()
{
    //IDemo partialStub = MockRepository.GenerateStub<IDemo>();
    IDemo partialStub = new MockRepository().Stub<IDemo>();
 
    //This line does not work unless I have called the above .Stub<IDemo>
    //partialStub
    //    .Stub<IDemo, string>((x) => { return x.ReturnStringWithInt32Arg(30); })
    //    .IgnoreArguments()
    //    .Do(
    //        (Func<int, string>)((arg) =>
    //        {
    //            return string.Format(
    //                "{0}{1}",
    //                new string('0', 6 - arg.ToString().Length), arg);
    //        })
    //    );
 
    //If I comment the above line out, it gives me this error on SetupResult below
    //Test method ThinkFarAhead.LearningMocking.Expectations.SetupResult2.TestRhinoAndMoq.Working threw exception:
    //System.InvalidOperationException: Invalid call, the last call has been used or 
    //no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method)..
    //This error occurs both when I create the Stub using MockRepository.GenerateStub<IDemo>() or new MockRepository().Stub<IDemo>()
    //SetupResult.For((Action<IDemo>)(x => x.ReturnStringWithInt32Arg(30))).IgnoreArguments()
    //  .Do((Func<int, string>)((arg) =>
    //  {
    //      return string.Format(
    //          "{0}{1}",
    //          new string('0', 6 - arg.ToString().Length), arg);
    //  }
    //    ));
 
    SetupResult
        .For(partialStub.ReturnStringWithInt32Arg(20))
        .IgnoreArguments()
        .Do((Func<int, string>)((arg) =>
            {
                return string.Format(
                    "{0}{1}",
                    new string('0', 6 - arg.ToString().Length), arg);
            }
        ));
 
    partialStub.Replay();
    Assert.AreEqual("000020", partialStub.ReturnStringWithInt32Arg(20));
    Assert.AreEqual("000030", partialStub.ReturnStringWithInt32Arg(30));
    Assert.AreEqual("000040", partialStub.ReturnStringWithInt32Arg(40));
}

1 comment:

Pradeep said...

Its very useful. Thanks a lot.