1

I found a really strange problem while creating unit tests that only occurs with the Mono runtime (Xamarin on Mac included), but runs fine within Visual Studio. I isolated it as far as I could, and I reached a point that I can't tell if it is a bug with Mono, Moq or Castle DinamicProxy, although it only crashes when using the Mono runtime.

This is the code:

using System;
using System.Collections.Generic;
using Moq;

namespace ConsoleApplication1
{
    public interface ISomething<T>
    {
        List<T> DoSomething<U>(/*Func<T, U> expression*/);
    }

    public class Foo { }

    public class Program
    {
        public static void Main(string[] args) {
            var mock = new Mock<ISomething<Foo>>();
            Console.WriteLine(mock.Object);
        }
    }
}

Here's that I know:

  1. It compiles and run with within Visual Studio 2012. The output is "Castle.Proxies.ISomething`1Proxy"
  2. It does not work when running with the Mono runtime. An exception is thrown (see below)
  3. If I change the declaration from an interface to an abstract class, it works with Mono
  4. If I change the return type from List<T> to anything else, it works with Mono
  5. If I remove the generic type <U>, it works with mono
  6. Got the same results under Windows, Mac and Linux using the command line build from http://mono-project.com
  7. In Windows it fails with Mono 2.10.9, but works within Xamarin.Studio (4.0.10)
  8. In Mac, it fails within Xamarin.Studio (4.0.10)
  9. I recompiled Moq linking agains the latest DynamicProxy release (Castle.Core.3.2.0), with no changed to the behaviour.

Although I've found this problem when using Moq, but I can't tell if it's related to it or even DynamicProxy. The partial exception is below, complete can be found at http://pastie.org/8203093

mono ConsoleApplication1.exe

[ERROR] FATAL UNHANDLED EXCEPTION: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
  at System.Collections.Generic.Dictionary`2[System.String,System.Reflection.Emit.GenericTypeParameterBuilder].get_Item (System.String key) [0x00000] in <filename unknown>:0
  at Castle.DynamicProxy.Internal.TypeUtil.CloseGenericParametersIfAny (Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter emitter, System.Type[] arguments) [0x00000] in <filename unknown>:0
  at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget (System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, Castle.DynamicProxy.IInterceptor[] interceptors) [0x00000] in <filename unknown>:0
  at Moq.Proxy.CastleProxyFactory.CreateProxy[ISomething`1] (ICallInterceptor interceptor, System.Type[] interfaces, System.Object[] arguments) [0x00000] in <filename unknown>:0
  [....]
  at Moq.Mock`1[ConsoleApplication1.ISomething`1[ConsoleApplication1.Foo]].<InitializeInstance>b__0 () [0x00000] in <filename unknown>:0
  at Moq.PexProtector.Invoke (System.Action action) [0x00000] in <filename unknown>:0
  at Moq.Mock`1[ConsoleApplication1.ISomething`1[ConsoleApplication1.Foo]].InitializeInstance () [0x00000] in <filename unknown>:0
  at Moq.Mock`1[ConsoleApplication1.ISomething`1[ConsoleApplication1.Foo]].OnGetObject () [0x00000] in <filename unknown>:0
  at Moq.Mock.GetObject () [0x00000] in <filename unknown>:0
  at Moq.Mock.get_Object () [0x00000] in <filename unknown>:0
  at Moq.Mock`1[ConsoleApplication1.ISomething`1[ConsoleApplication1.Foo]].get_Object () [0x00000] in <filename unknown>:0
  at ConsoleApplication1.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
Rafael Steil
  • 4,538
  • 4
  • 25
  • 30
  • 1
    Mono does not fully support code generation and reflection that is used by libraries like Castle. You can give a try mono 3, which has been in beta for a while. – alex Aug 03 '13 at 15:45
  • 1
    I fixed recently a bug in mono that was affecting my Castle.DynamicProxy unit tests too; my fix was included in Mono 3.2, so you should give this version a try – knocte Aug 03 '13 at 20:04
  • I am facing exactly the same problem right now! I am using 3.2.0! – prnjanuario Sep 03 '13 at 19:24
  • Yes, the problem still lies on 3.2. What I did was to change the method's signature, which was an option in my case. – Rafael Steil Sep 03 '13 at 22:47

0 Answers0