devlooped/moq · error · NotSupportedException

Resources.CallBaseCannotBeUsedWithDelegateMocks

Error message

Resources.CallBaseCannotBeUsedWithDelegateMocks

What it means

MethodCall.SetCallBaseBehavior throws NotSupportedException because CallBase cannot be used when the mocked type is a delegate. Delegates have no base implementation to invoke, so the CallBase behavior is meaningless and rejected.

Solutions

  1. Remove the CallBase() call for delegate mocks
  2. Provide an explicit Returns()/callback implementation instead
  3. If base behavior is needed, mock an interface or class with a real implementation rather than a delegate

Example fix

// before
var mock = new Mock<Func<int, int>>();
mock.CallBase = true;
// after
var mock = new Mock<Func<int, int>>();
mock.Setup(f => f(42)).Returns(100);
Defensive patterns

Strategy: validation

Validate before calling

if (mockedType.IsDelegateType()) throw new InvalidOperationException("CallBase is not supported for delegate mocks");

Type guard

static bool IsDelegateMock<T>() => typeof(T).IsSubclassOf(typeof(Delegate)) || typeof(T) == typeof(Delegate);

Try / catch

try { mock.CallBase = true; } catch (NotSupportedException ex) when (ex.Message.Contains("delegate")) { /* use explicit Returns instead */ }

Prevention

When it happens

Trigger: Setting up a delegate mock (e.g. Mock<Func<int,int>> or Mock<EventHandler>) and calling `.CallBase()` on the setup or mock.

Common situations: Developers mocking delegates (common in event handler or legacy callback scenarios) who attempt CallBase to fall through to the delegate's original target.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16). Data as JSON: /api/errors/16b8f1b7dec8049a. Report an issue: GitHub.

Appendix: source

Thrown at src/Moq/MethodCall.cs:134

                }
                else
                {
                    new ReturnBaseOrDefaultValue(this.Mock).Execute(invocation);
                }
            }
            else
            {
                HandleEventSubscription.Handle(invocation, this.Mock);  // no-op for everything other than event accessors
            }

            this.afterReturnCallback?.Execute(invocation);
        }

        public void SetCallBaseBehavior()
        {
            if (this.Mock.MockedType.IsDelegateType())
            {
                throw new NotSupportedException(Resources.CallBaseCannotBeUsedWithDelegateMocks);
            }

            this.returnOrThrow = ReturnBase.Instance;
        }

        public void SetCallbackBehavior(Delegate callback)
        {
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            ref Behavior? behavior = ref (this.returnOrThrow == null) ? ref this.callback
                                                                     : ref this.afterReturnCallback;

            if (callback is Action callbackWithoutArguments)
            {
                behavior = new Callback(_ => callbackWithoutArguments());

View on GitHub (pinned to 89a5be629c)