{"record":{"id":"2825e79a050a1e56","repo":"mockito/mockito","slug":"wanted-never-wanted-here-location-but-invok","errorCode":null,"errorMessage":"${wanted}\nNever wanted here:\n${location}\nBut invoked here:\n${locations with arguments}","messagePattern":"(.+?)\nNever wanted here:\n(.+?)\nBut invoked here:\n(.+?)","errorType":"exception","errorClass":"NeverWantedButInvoked","httpStatus":null,"severity":"error","filePath":"mockito-core/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java","lineNumber":43,"sourceCode":"import org.mockito.invocation.Location;\nimport org.mockito.invocation.MatchableInvocation;\n\npublic class NumberOfInvocationsChecker {\n\n    private NumberOfInvocationsChecker() {}\n\n    public static void checkNumberOfInvocations(\n            List<Invocation> invocations, MatchableInvocation wanted, int wantedCount) {\n        List<Invocation> actualInvocations = findInvocations(invocations, wanted);\n\n        int actualCount = actualInvocations.size();\n        if (wantedCount > actualCount) {\n            List<Location> allLocations = getAllLocations(actualInvocations);\n            throw tooFewActualInvocations(\n                    new Discrepancy(wantedCount, actualCount), wanted, allLocations);\n        }\n        if (wantedCount == 0 && actualCount > 0) {\n            throw neverWantedButInvoked(wanted, actualInvocations);\n        }\n        if (wantedCount < actualCount) {\n            throw tooManyActualInvocations(\n                    wantedCount, actualCount, wanted, getAllLocations(actualInvocations));\n        }\n\n        markVerified(actualInvocations, wanted);\n    }\n\n    public static void checkNumberOfInvocations(\n            List<Invocation> invocations,\n            MatchableInvocation wanted,\n            int wantedCount,\n            InOrderContext context) {\n        List<Invocation> chunk = findMatchingChunk(invocations, wanted, wantedCount, context);\n\n        int actualCount = chunk.size();\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/mockito/mockito/blob/5a676bcd9ef9a10db46e1dc34e190eb46faa2687/mockito-core/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java#L25-L61","documentation":"Mockito's never() verification failed: the test marked a method as never wanted (times(0)), but it was invoked at least once. NumberOfInvocationsChecker throws NeverWantedButInvoked, listing the location and arguments of each offending invocation so the developer can see exactly which call should not have happened.","triggerScenarios":"verify(mock, never()).method(); verify(mock, times(0)).method(); verifyNoMoreInteractions-style flows hitting the wantedCount == 0 && actualCount > 0 branch in checkNumberOfInvocations.","commonSituations":"Testing an error/fallback path but the happy path still ran; a retry loop still fired the call the test thought was suppressed; verifying the wrong argument matcher so a legitimate call registers as the forbidden one; regression where new code added a call that a safety-net test forbids.","solutions":["Inspect the 'But invoked here' locations/arguments in the message to identify which code path made the forbidden call.","Fix the code under test so the forbidden path is not executed (guard clauses, early returns, correct configuration).","If the call is actually legitimate now, update the test: replace never() with times(n) or atLeastOnce().","Check stubbing: an incorrectly stubbed method or a spy calling real code can trigger unexpected invocations; use doReturn().when() on spies instead of when()."],"exampleFix":"// before\nverify(payments, never()).charge(any()); // but refund path also charges\n\n// after: fix code so only refund logic runs, or update expectation\nverify(payments, times(1)).charge(any());","handlingStrategy":"try-catch","validationCode":"long actual = Mockito.mockingDetails(mock).getInvocations().stream()\n    .filter(i -> i.getMethod().getName().equals(\"charge\")).count();\nif (actual > 0 && expectingNoCharge) throw new AssertionError(\"forbidden charge() executed \" + actual + \"x\");","typeGuard":null,"tryCatchPattern":"try {\n    verify(payments, never()).charge(any());\n} catch (NeverWantedButInvoked e) {\n    // message lists the offending call site — route to failure diagnostics\n    throw new AssertionError(\"forbidden path executed: \" + e.getMessage(), e);\n}","preventionTips":["Stub spies with doReturn().when(spy).method() to avoid invoking real code that triggers forbidden calls.","Keep never() assertions focused on a single guard condition; assert the error/branch path was taken too.","Re-check never() expectations after refactors that add new call sites.","Use the arguments in the failure message to confirm whether the matcher wrongly matched a legitimate call."],"tags":["mockito","verification","never","test"],"backgroundTag":"mockito-never-wanted-but-invoked","analyzedSha":"5a676bcd9ef9a10db46e1dc34e190eb46faa2687","analyzedAt":"2026-09-05T19:32:58.607Z","contentChangedAt":"2026-09-05T19:32:58.607Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}