devlooped/moq · error · InvalidOperationException
InvalidOperationException (unhandled Times kind in…
Error message
InvalidOperationException (unhandled Times kind in GetExceptionMessage)
What it means
Times.GetExceptionMessage(callCount) picks a resource string by Kind and throws InvalidOperationException when the kind is unrecognized. Like the ToString guard, it signals a Times value carrying an invalid Kind at the moment Moq formats a 'no matching calls' verification failure message.
Solutions
- Use only the public Times factories to create instances
- Unify Moq package versions across the solution to eliminate enum/value skew
- If unavoidable, wrap Verify calls in try-catch for InvalidOperationException to produce a diagnosable failure, and report the Moq bug
Example fix
// before var times = default(Times); // Kind = 0 default may still be invalid if constructed raw // after var times = Times.AtLeastOnce();
Defensive patterns
Strategy: try-catch
Try / catch
try
{
mock.Verify(m => m.Foo(), times);
}
catch (InvalidOperationException ex)
{
// invalid Times kind reached GetExceptionMessage; rebuild and retry
times = Times.AtLeastOnce();
mock.Verify(m => m.Foo(), times);
} Prevention
- Construct Times only through public static factories
- Avoid reflection or deserialization of Moq internal types
- Keep Moq versions consistent across test projects
When it happens
Trigger: A Times instance with an out-of-range Kind reaches verification-failure message formatting — via invalid construction, deserialization, or mixed Moq assembly versions.
Common situations: Same as the ToString invariant break: hand-built Times values, assembly version skew in the test runner, corrupted state.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- InvalidOperationException (unhandled Times kind in ToString)
- Unsupported expression
- Could not determine the correct positions for all argument…
- The return type of the last member shown above is not…
- Value cannot be null. (Parameter 'value')
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/584ae93c5e9aa923.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Times.cs:280
if (this.kind == Kind.BetweenExclusive)
{
--from;
++to;
}
var message = this.kind switch
{
Kind.AtLeastOnce => Resources.NoMatchingCallsAtLeastOnce,
Kind.AtLeast => Resources.NoMatchingCallsAtLeast,
Kind.AtMost => Resources.NoMatchingCallsAtMost,
Kind.AtMostOnce => Resources.NoMatchingCallsAtMostOnce,
Kind.BetweenExclusive => Resources.NoMatchingCallsBetweenExclusive,
Kind.BetweenInclusive => Resources.NoMatchingCallsBetweenInclusive,
Kind.Exactly => Resources.NoMatchingCallsExactly,
Kind.Once => Resources.NoMatchingCallsOnce,
Kind.Never => Resources.NoMatchingCallsNever,
_ => throw new InvalidOperationException(),
};
return string.Format(CultureInfo.CurrentCulture, message, from, to, callCount);
}
/// <summary>
/// Checks whether the specified number of invocations matches the constraint described by this instance.
/// </summary>
/// <param name="count">The number of invocations to check.</param>
/// <returns>
/// <see langword="true"/> if <paramref name="count"/> matches the constraint described by this instance;
/// otherwise, <see langword="false"/>.
/// </returns>
public bool Validate(int count)
{
var (from, to) = this;
return from <= count && count <= to;
}View on GitHub (pinned to 89a5be629c)