AutoMock CreateInstance Type to mock must be an interface, a delegate, or a non-sealed, non-static class

6.3k views Asked by At

I get the generic message below when mocking "autoMocker.CreateInstance<HeliumController>();" with Moq.AutoMock.Automocker. The HeliumController class's constructor take several interfaces. How can I find which specific interface or constructor is failing to mock?

{System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.NotSupportedException: Type to mock must be an interface, a delegate, or a non-sealed, non-static class.
   at Moq.Guard.IsMockable(Type type)
   at Moq.Mock`1..ctor(MockBehavior behavior, Object[] args)
   at Moq.Mock`1..ctor(MockBehavior behavior)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Moq.AutoMock.Resolvers.MockResolver.Resolve(MockResolutionContext context)
   at Moq.AutoMock.AutoMocker.Resolve(Type serviceType, Object initialValue)
   at Moq.AutoMock.AutoMocker.Resolve(Type serviceType)
   at Moq.AutoMock.AutoMocker.Get(Type serviceType)
   at Moq.AutoMock.AutoMocker.<CreateArguments>b__58_0(ParameterInfo x)
   at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Moq.AutoMock.AutoMocker.CreateArguments(Type type, BindingFlags bindingFlags)
   at Moq.AutoMock.AutoMocker.CreateInstance(Type type, Boolean enablePrivate)
   at Moq.AutoMock.AutoMocker.CreateInstance[T](Boolean enablePrivate)
   at Moq.AutoMock.AutoMocker.CreateInstance[T]()
   at Helium.Api.Tests.API.v2.HeliumControllerSearchTests..ctor()
2

There are 2 answers

0
Mystic Lin On

In my case, <InternalsVisibleTo Include="DynamicProxyGenAssembly2" /> can solve this issue.

0
Travis Illig On

Unfortunately it's going to be some trial and error, looking through the types that the constructor takes and then looking to see if any of those don't fit the requirements - I'd first start and look at the sealed classes you're using, since that's probably the cause. Interfaces, non-sealed, non-static, and delegate - those can all be mocked.

I did notice you don't have any line numbers in the exception. I gather things might be getting tested in a "Release" mode so symbols aren't available. Usually exception stacks in "Debug" mode have the actual line number on which the exception occurred - it might help to compile and run the test in "Debug" mode to see the actual line. That could narrow it down.

Here's where the not-mockable exception is thrown in Moq. It appears they could pretty easily add the actual type name to the exception, it's just not happening. If I were you, I'd file an issue with the Moq folks and ask them to update to include the type name in the exception. If they're OK with that, it seems like it might be a pretty easy pull request to submit to them and make the product better, at the same time solving your problem.