AutoMocking interfaces with events throws DynamicProxy2 exception (UPDATED)
description
(UPDATED unit test attached -- still fails after incorporating fix suggested by baxevanis with Moq v4.0.10827)
When I use AutoFixture (v2.9.2, with AutoMoqCustomization -- with Moq v 4.0.10827 and the appropriate dependentAssembly bindingRedirect) to Freeze and inject a mock of an interface that contains an event into my SUT, the following exception is thrown when my event is wired up inside the SUT:
System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.NotImplementedException : This is a DynamicProxy2 error: The interceptor attempted to 'Proceed' for method 'Void add_Fire(System.EventHandler)' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)
at System.RuntimeMethodHandle._InvokeConstructor(IRuntimeMethodInfo method, Object[] args, ref SignatureStruct signature, RuntimeType declaringType)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
at Ploeh.AutoFixture.Kernel.MethodInvoker.Create(Object request, ISpecimenContext context)
at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault(IEnumerable1 source)
at Ploeh.AutoFixture.Kernel.Postprocessor1.Create(Object request, ISpecimenContext context)
at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault(IEnumerable1 source)
at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault(IEnumerable1 source)
at Ploeh.AutoFixture.Kernel.Postprocessor1.Create(Object request, ISpecimenContext context)
at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b)
at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault(IEnumerable1 source)
at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context)
at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous(ISpecimenContext context, T seed)
at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous(ISpecimenContext context)
at MyNamespace.AutoFixtureEventsExploratoryTests.ThisDoesNotWork() in AutoFixtureEventsExploratoryTests.cs: line 18
--NotImplementedException
at Castle.DynamicProxy.AbstractInvocation.ThrowOnNoTarget()
at Castle.DynamicProxy.CompositionInvocation.EnsureValidTarget()
at Castle.Proxies.Invocations.IMyEventRaisingInterface_add_Fire.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Moq.Interceptor.Intercept(ICallContext invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at MyNamespace.MyClass..ctor(IMyEventRaisingInterface trigger) in AutoFixtureEventsExploratoryTests.cs: line 51
Also, I noticed that the same test fails differently when using the exact version of Moq (matching the NuGet package's dependency) -- in this case the event simply never fires (or the registered handler in the SUT class never gets invoked, so the Assert fails.