{"record":{"id":"de531002e1cc1e67","repo":"sebastianbergmann/phpunit","slug":"no-entry-in-the-value-map-matched-the-invocation-o","errorCode":null,"errorMessage":"No entry in the value map matched the invocation of %s::%s() with parameters (%s)","messagePattern":"No entry in the value map matched the invocation of (.+?)::(.+?)\\(\\) with parameters \\((.+?)\\)","errorType":"exception","errorClass":"ExpectationFailedException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php","lineNumber":64,"sourceCode":"     */\n    public function invoke(Invocation $invocation): mixed\n    {\n        $parameterCount = count($invocation->parameters());\n\n        foreach ($this->valueMap as $map) {\n            if (!is_array($map) || $parameterCount !== (count($map) - 1)) {\n                continue;\n            }\n\n            $return = array_pop($map);\n\n            if ($this->parametersMatch($map, $invocation->parameters())) {\n                return $return;\n            }\n        }\n\n        if ($this->strict) {\n            throw new ExpectationFailedException(\n                sprintf(\n                    'No entry in the value map matched the invocation of %s::%s() with parameters (%s)',\n                    $invocation->className(),\n                    $invocation->methodName(),\n                    Exporter::shortenedExport($invocation->parameters()),\n                ),\n            );\n        }\n\n        return null;\n    }\n\n    /**\n     * @param array<mixed> $mapParameters\n     * @param array<mixed> $invocationParameters\n     */\n    private function parametersMatch(array $mapParameters, array $invocationParameters): bool\n    {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php#L46-L82","documentation":"ReturnValueMap is the stub behind returnValueMap() (non-strict) and willReturnMap() (strict). On each invocation it looks for a map row whose parameter segment matches the invocation's arguments (same arity, strict === comparison or Constraint evaluation); the last element of the row is the return value. In strict mode (willReturnMap), when no row matches, PHPUnit throws ExpectationFailedException instead of silently returning null, so an unmatched call cannot hide as a null that later fails somewhere else.","triggerScenarios":"$mock->method('get')->willReturnMap([['a', 1], ['b', 2]]) followed by $mock->get('c'): no row's parameter segment equals ['c'], so with strict=true the 'No entry in the value map matched ... with parameters (...)' exception is thrown at call time inside the test. Non-matching rows are silently skipped when their arity differs (count($map) - 1 !== parameterCount) or their values differ under strict comparison.","commonSituations":"A default-argument call omits a parameter the map rows include (or vice versa), so arity check rejects every row; values that look equal but differ in type (0 vs '0', null vs '', false vs 0) under the strict !== comparison; passing objects that are equal-but-not-identical instances; forgetting that the return value must be the LAST element of each row; enums/named-argument reordering changes what the SUT actually passes.","solutions":["Add a map row for the actually-passed parameters (copy them from the exception message, which prints the exact invocation parameters via Exporter::shortenedExport).","Fix arity: every row must have exactly one more element than the method's argument count for that call site, and default arguments must be spelled out in the row.","Use constraints instead of literals in rows (equalTo with loose settings, isType, callback, instanceof) when exact identity cannot be guaranteed.","If unmatched calls returning null is acceptable, use the non-strict returnValueMap() instead of willReturnMap(); better still, switch to willReturnCallback() for full control over matching and defaults."],"exampleFix":"// before\n$cache->method('get')\n     ->willReturnMap([['user-1', $user], ['user-2', $user2]]);\n$cache->get('user-3'); // strict mode -> ExpectationFailedException\n\n// after\n$cache->method('get')\n     ->willReturnMap([\n         ['user-1', $user],\n         ['user-2', $user2],\n         ['user-3', null],  // explicit fallback row\n     ]);","handlingStrategy":"validation","validationCode":"// Validate map rows against the method signature before wiring the stub:\n$map = [\n    ['user-1', $u1],\n    ['user-2', $u2],\n    ['user-3', null], // default row for any key\n];\n$paramCount = (new ReflectionMethod(Cache::class, 'get'))->getNumberOfRequiredParameters();\nforeach ($map as $row) {\n    assert(count($row) === $paramCount + 1, 'each row = params + return value');\n}","typeGuard":"// Narrow a value before putting it into a map row when strict identity matters:\nfunction isCacheableKey(mixed $key): bool\n{\n    return is_string($key) && preg_match('/^[a-z0-9-]+$/', $key) === 1;\n}","tryCatchPattern":"use PHPUnit\\Framework\\ExpectationFailedException;\n\ntry {\n    $sut->lookup($key);\n} catch (ExpectationFailedException $e) {\n    if (str_contains($e->getMessage(), 'No entry in the value map matched')) {\n        self::fail('Add a willReturnMap row for parameters: ' . $e->getMessage());\n    }\n    throw $e;\n}","preventionTips":["Every row: [param1, ..., paramN, returnValue] — the return value is always last and arity must be params+1.","Watch strict comparison: 0 !== '0', null !== false; export the actual parameters from the message and diff them.","Use PHPUnit constraints inside rows for fuzzy matches.","Choose returnValueMap() (non-strict, returns null) only when a null default is acceptable; keep willReturnMap() strict otherwise."],"tags":["phpunit","mockobject","stub","return-value-map","strict-matching"],"backgroundTag":"mock-return-value-map-miss","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}