devlooped/moq · error · ArgumentException

Method . is public. Use strong-typed Expect overload…

Error message

Method {0}.{1} is public. Use strong-typed Expect overload instead:
mock.Setup(x => x.{1}());

What it means

ProtectedMock's InternalSetup/InternalSetupSequence/InternalVerify guard against accidentally using the Protected API for a public method. If the resolved member is public, ThrowIfPublicMethod throws ArgumentException with Resources.MethodIsPublic telling you to use the strong-typed Expect overload: mock.Setup(x => x.Method()). The Protected API is strictly for non-public members.

Solutions

  1. Use the strong-typed API: mock.Setup(x => x.Method()) / mock.Verify(x => x.Method())
  2. If you truly need protected semantics, confirm the method is still non-public in the version you mock
  3. Pin/adjust for the library version — if the method became public, migrate the test to typed setups

Example fix

// before
mock.Protected().Setup("Save", ItExpr.IsAny<string>());
// after
mock.Setup(x => x.Save(It.IsAny<string>())); // Save is public
Defensive patterns

Strategy: validation

Validate before calling

static bool IsProtected(Type t, string member) =>
    t.GetMethod(member, BindingFlags.NonPublic | BindingFlags.Instance) is MethodInfo m && !m.IsPublic;

Try / catch

try { mock.Protected().Setup("Save", ItExpr.IsAny<string>()); }
catch (ArgumentException ex) when (ex.Message.Contains("is public")) { /* switch to mock.Setup(x => x.Save(...)) */ }

Prevention

When it happens

Trigger: mock.Protected().Setup("PublicMethod") or .As<TAnalog>() setups where the matched method on T is public (e.g. the method was made public in a newer version, or the wrong member-name string resolved to a public method).

Common situations: Library upgrade changed a method from protected to public; developer assumed the method was protected without checking; analog-type rewriting resolved to a public member.

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


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

Appendix: source

Thrown at src/Moq/Protected/ProtectedMock.cs:415

                    }
                }

                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.MethodMissing,
                    typeof(T).Name,
                    methodName,
                    string.Join(
                        ", ",
                        extractedTypeNames.ToArray())));
            }
        }

        static void ThrowIfPublicMethod(MethodInfo method, string reflectedTypeName)
        {
            if (method.IsPublic)
            {
                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.MethodIsPublic,
                    reflectedTypeName,
                    method.Name));
            }
        }

        static void ThrowIfPublicGetter(PropertyInfo property, string reflectedTypeName)
        {
            if (property.CanRead(out var getter) && getter.IsPublic)
            {
                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.UnexpectedPublicProperty,
                    reflectedTypeName,
                    property.Name));
            }
        }

View on GitHub (pinned to 89a5be629c)