#32 Mocking IL interfaces with explicitly [in] marked parameters

open
nobody
nmock2 (11)
5
2008-11-10
2008-11-10
Anonymous
No

The following IL method declaration is part of an interface generated by the Typelib importer.

...

.method public hidebysig newslot abstract virtual instance int32
GetItem(
[in] string marshal( bstr) bstrItemName,
[out] object& marshal( iunknown ) ppItem)
runtime managed internalcall preservesig
{
}

...

When trying to mock this interface by nmock2 mocks I get an exception from the Microsoft RealProxy implementation:

System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

My Testcode:
...
[Test]
public void TestOutParameter()
{
Mockery mockery = new Mockery();
IItemprovider itemProvider =
(IItemprovider)mockery.NewMock(typeof IItemprovider));
object obj = new object();

Expect.Once.On(itemProvider).Method("GetItem")
.With("item", Is.Out)
.Will(new SetIndexedParameterAction(1, obj), Return.Value(0));

object temp;
itemProvider.GetItem("item", out temp);
Assert.AreEqual(obj, temp);
}
...

Debugging showed that the problem seems to be handling of In parameters in the ProxyInvokableAdapter.CollectOutputArguments method.

Explanation: AFAIK it is not possible to mark parameters as [in] parameters in C# code (or any other non IL programming language). So normally _all_ parameters will be transferred to the output arguments collection, which does seem to be what the dotnet RealProxy expects since it is accessing the output and parameters arrays in RealProxy.PropagateOutParameters with the same index. However, since the first parameter in the method on top is marked as [in] those arrays do not match anymore and the RealProxy tries to access the index "1" in the ouputparameter which does only have one entry at "0".

For any further questions contact me under dirk.peters.ath@gmx.de.

Discussion

  • I have to correct myself: It is possible to mark parameters as [In] parameters with attributes in C#.