views:

147

answers:

1

Hi,

How could I mock a void method with parameters and change the value parameters?

I want to test a class (SomeClassA) which has a dependency on another class (SomeClassB). I would like to mock SomeClassB.


public class SomeClassA
{
   private SomeClassB objectB;    
   private bool GetValue(int x, object y)
   {
      objectB.GetValue(x, y);      // This function takes x and change the value of y
   }
}

SomeClassB implements interface IFoo


public interface IFoo 
{
   public void GetValue(int x, SomeObject y)     // This function takes x and change the value of y
}

pulic class SomeClassB : IFoo
{
   // Table of SomeObjects 
   public void GetValue(int x, SomeObject y)
   {
       // Do some check on x
       // If above is true get y from the table of SomeObjects
   }
}

Then in my unit test class, I prepared a delegate class which mimic SomeClassB.GetValue:


private delegate void GetValueDelegate(int x, SomeObject y);
private void GetValue(int x, SomeObject y)
{  // process x
   // prepare a new SomeObject obj
   SomeObject obj = new SomeObject();
   obj.field = x;
   y = obj;
}

In the mock part I wrote:


IFoo myFooObject = mocks.DynamicMock();
Expect.Call(delegate { myFooObject.Getvalue(5, null); }).Do(new GetValueDelegate(GetValue)).IgnoreArguments().Repeat.Any();

SomeObject o = new SomeObject();

myFooObject.getValue(5, o);
Assert.AreEqual(5, o.field);   // This assert fails!

I checked a couple of posts and delegate seems to be the key to mock a void method. However, after trying the above, it's not working. Could you advise if there is anything wrong in my delegate class? Or something wrong in the mock statement?


My RhinoMocks is 3.5 and seems like it's dropping the Do part if I include IgnoreArguments() I just found this page: http://www.mail-archive.com/[email protected]/msg00287.html

Now I have changed

Expect.Call(delegate { myFooObject.Getvalue(5, null); }).Do(new GetValueDelegate(GetValue)).IgnoreArguments().Repeat.Any();

to

Expect.Call(delegate { myFooObject.Getvalue(5, null); }).IgnoreArguments().Do(new GetValueDelegate(GetValue)).Repeat.Any();

And now it works perfectly fine!

A: 

Kar, are you using a really old version .NET or something? This syntax has been outdated for quite some time. I also think that you're doing it wrong. Rhino Mocks isn't magic - it doesn't do anything you couldn't do yourself using a couple extra lines of code.

For example if I have

public interface IMakeOrders {
  bool PlaceOrderFor(Customer c);
}

I can implement it with:

public class TestOrderMaker : IMakeOrders {
  public bool PlaceOrderFor(Customer c) {
    c.NumberOfOrders = c.NumberOfOrder + 1;
    return true;
  }
}

or

var orders = MockRepository.GenerateStub<IMakeOrders>();
orders.Stub(x=>x.PlaceOrderFor(Arg<Customer>.Is.Anything)).Do(new Func<Customer, bool> c=> {
    c.NumberOfOrders = c.NumberOfOrder + 1;
    return true;  
});

Read this intro to RM that I wrote up for some contractors.

George Mauer
thanks george! yes i'm still using .net 2.0 (so now we would like to have it to be upgraded to 3.5...but that will take a while...) your code looks very neat and clean. and thanks for your intro it's really helpful. :)
Kar