devlooped/moq · error · ArgumentException
Resources.AsMustBeInterface
Error message
Resources.AsMustBeInterface
What it means
Moq throws this ArgumentException when Mock<T>.As<TInterface>() is called with a TInterface that is not an interface. As<T>() exists to add additional interface implementations to a mock, so only interface type arguments are legal.
Solutions
- Only pass interface types to As<TInterface>.
- To cast the mock itself, use (Mock<TDerived>)mock or As<TDerived> only when TDerived is an interface the type can implement.
- Add a 'where TInterface : class' + runtime IsInterface check in generic wrappers before calling As.
Example fix
// before var m = mock.As<MyBaseClass>(); // after var m = mock.As<IDerivedInterface>();
Defensive patterns
Strategy: type-guard
Validate before calling
if (!typeof(TInterface).IsInterface)
throw new ArgumentException("As<TInterface> requires an interface type."); Type guard
bool IsInterfaceArg<TInterface>() => typeof(TInterface).IsInterface;
Try / catch
try { return mock.As<TInterface>(); } catch (ArgumentException ex) when (ex.Message.Contains("interface")) { throw new InvalidOperationException("Pass an interface type to As<T>."); } Prevention
- Only pass interfaces to As<T>()
- In generic wrappers constrain or runtime-check TInterface.IsInterface
- Use a plain cast for class types instead of As<T>
When it happens
Trigger: mock.As<SomeClass>() or mock.As<SomeStruct>() — any call to As<TInterface> where typeof(TInterface).IsInterface is false (src/Moq/Mock`1.cs:384).
Common situations: Using As<T>() to cast to a base class (mistakenly thinking it performs a cast); generic code with an unconstrained T passed to As<T>.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Resources.ArgumentMatcherWillNeverMatch (formatted with…
- Resources.InvalidCallbackParameterMismatch (formatted with…
- Resources.ConstructorArgsForInterface
- Resources.ConstructorArgsForDelegate
- Resources.AlreadyInitialized
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/3f6dd07f6baefb46.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Mock`1.cs:384
/// The following example creates a mock for the main interface
/// and later adds <see cref="IDisposable"/> to it to verify it's called by the consumer code:
/// <code>
/// var mock = new Mock<IProcessor>();
/// mock.Setup(x => x.Execute("ping"));
///
/// // add IDisposable interface
/// var disposable = mock.As<IDisposable>();
/// disposable.Setup(d => d.Dispose())
/// .Verifiable();
/// </code>
/// </example>
public override Mock<TInterface> As<TInterface>()
{
var interfaceType = typeof(TInterface);
if (!interfaceType.IsInterface)
{
throw new ArgumentException(Resources.AsMustBeInterface);
}
if (typeof(TInterface) == typeof(T))
{
return (Mock<TInterface>)(Mock)this;
}
if (this.IsObjectInitialized && this.ImplementsInterface(interfaceType) == false)
{
throw new InvalidOperationException(Resources.AlreadyInitialized);
}
if (this.AdditionalInterfaces.Contains(interfaceType) == false)
{
// We get here for either of two reasons:
//
// 1. We are being asked to implement an interface that the mocked type does *not* itself
// inherit or implement. We need to hand this interface type to DynamicProxy'sView on GitHub (pinned to 89a5be629c)