With Rhino Mocks, how do I intercept a call to a single property on an interface, passing everything else to a "default implementation"?

I have an IComplex interface with many methods and properties, I want to create a โ€œlayoutโ€ that forces the โ€œConfigโ€ property to return an object of my choice, passing all the other calls to the โ€œrealโ€ instance of IComplex.

Just to make it a little harder, we still use C # V2!

+4
source share
3 answers

As far as I know, there is no way to configure multiple layout methods at once. You need to specify all the methods for sending them to another implementation ...

... if you have not written a reflection code to customize the layout.

Here is the (working) code. It uses C # 3.0, but the main part is the old-style Rhino Mocks style that was written for C # 2.0.

public static class MockExtensions { public static void ForwardCalls<T>(this T mock, T original) { mock.BackToRecord(); Type mockType = typeof(T); var methods = mockType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Union(mockType.GetInterfaces().SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.Instance))); foreach (MethodInfo method in methods) { List<object> args = new List<object>(); foreach (var arg in method.GetParameters()) { args.Add(CreateDefaultValue(arg.ParameterType)); } method.Invoke(mock, args.ToArray()); var myMethod = method; if (method.ReturnType == typeof(void)) { LastCall .IgnoreArguments() // not Repeat.Any to allow overriding the value .Repeat.Times(int.MaxValue) .WhenCalled(call => myMethod.Invoke(original, call.Arguments)); } else { LastCall .IgnoreArguments() // not Repeat.Any to allow overriding the value .Repeat.Times(int.MaxValue) .WhenCalled(call => call.ReturnValue = myMethod.Invoke(original, call.Arguments)) .Return(CreateDefaultValue(myMethod.ReturnType)); } } mock.Replay(); } private static object CreateDefaultValue(Type type) { if (type.IsValueType) { return Activator.CreateInstance(type); } else { return Convert.ChangeType(null, type); } } } 

Using:

 [TestClass] public class TestClass() { [TestMethod] public void Test() { var mock = MockRepository.GenerateMock<IList<int>>(); List<int> original = new List<int>(); mock.ForwardCalls(original); mock.Add(7); mock.Add(8); Assert.AreEqual(2, mock.Count); Assert.AreEqual(7, mock[0]); Assert.AreEqual(8, mock[1]); //fake Count after ForwardCalls, use Repeat.Any() mock.Stub(x => x.Count) .Return(88) .Repeat.Any(); // repeat any needed to "override" value // faked count Assert.AreEqual(88, mock.Count); } } 
+3
source

You can use the PartialMock method to create a layout.

You pass the type of the real class to this method and register only those calls that you need to make fun of.

Note that the methods you want to mock the IComplex implementation must be virtual in order to accomplish this.

See http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx for more details.

+1
source

You want to create a proxy object that passes all the calls to an instance of a real implementation, unless you want to override member behavior.

As far as I know, Rhino Mocks does not support this. However, you could create a mocking feature like the Dynamic Proxy Bookmark . (Rhino mocks uses the same library.)

+1
source

All Articles