{"record":{"id":"a69b45e089567fbf","repo":"devlooped/moq","slug":"resources-setupnoteventremove-formatted-with-part-expression","errorCode":null,"errorMessage":"Resources.SetupNotEventRemove (formatted with part.Expression)","messagePattern":"Resources\\.SetupNotEventRemove \\(formatted with part\\.Expression\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/Mock.cs","lineNumber":736,"sourceCode":"            if (parts.Count == 0)\n            {\n                EventInfo @event;\n                if (method.IsEventAddAccessor())\n                {\n                    var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());\n                    @event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)\n                                               .SingleOrDefault(e => e.GetAddMethod(true) == implementingMethod)\n                             ?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,\n                                                                          Resources.SetupNotEventAdd,\n                                                                          part.Expression));\n\n                }\n                else if (method.IsEventRemoveAccessor())\n                {\n                    var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());\n                    @event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)\n                                               .SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod)\n                             ?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,\n                                                                          Resources.SetupNotEventRemove,\n                                                                          part.Expression));\n\n                }\n                else\n                {\n                    throw new ArgumentException(\n                        string.Format(\n                            CultureInfo.CurrentCulture,\n                            Resources.UnsupportedExpression,\n                            expression));\n                }\n\n                if (mock.EventHandlers.TryGet(@event, out var handlers))\n                {\n                    var returnType = handlers.GetMethodInfo().ReturnType;\n                    if (returnType == typeof(Task) || returnType.FullName == \"System.Threading.Tasks.ValueTask\")\n                    {","sourceCodeStart":718,"sourceCodeEnd":754,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/Mock.cs#L718-L754","documentation":"Symmetric to the add-accessor case: when Raise resolves an event remove accessor (e => e.MyEvent -= null) but no event on the mock's concrete type exposes that method as its remove method, Moq throws ArgumentException with Resources.SetupNotEventRemove, because it cannot map the accessor back to its EventInfo.","triggerScenarios":"mock.Raise(x => x.SomeEvent -= null, ...) where the remove accessor comes from an explicitly implemented interface event, a hidden/new event, or a type whose events are not visible under the binding flags used, leaving GetEvents(...).SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod) empty.","commonSituations":"Explicit interface event implementations on mocked classes; duplicated event declarations across inheritance hierarchies; reflection over mock.Object.GetType() returning a subclass that hides the event.","solutions":["Use mock.As<IInterface>().Raise(e => e.Event -= null, args) targeting the declaring interface","Declare events once on a mockable (non-sealed) base and avoid hiding with 'new'","Check that the event's declaring type is accessible to Moq's reflection (public or internals visible to DynamicProxyGenAssembly2)","Invoke the event through production code or an OnEvent helper rather than Raise for exotic event layouts"],"exampleFix":"// before\nmock.Raise(x => x.HiddenEvent -= null, EventArgs.Empty); // accessor not resolvable -> throws\n// after\nmock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);","handlingStrategy":"try-catch","validationCode":"var evt = mock.Object.GetType().GetEvents()\n    .FirstOrDefault(e => e.GetRemoveMethod(true) != null && e.Name == nameof(IEventSource.SourceEvent));\n// null means Raise(e => e.SourceEvent -= null, ...) will throw","typeGuard":null,"tryCatchPattern":"try\n{\n    mock.Raise(x => x.SourceEvent -= null, EventArgs.Empty);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"SetupNotEventRemove\"))\n{\n    mock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);\n}","preventionTips":["Target the event's declaring interface with mock.As<T>().Raise rather than the concrete class","Keep event add/remove accessors compiler-generated (no custom event accessors that break reflection)","Avoid redeclaring events in derived mock types"],"tags":["moq","event","raise","remove-accessor"],"backgroundTag":"resource-not-found","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}