sebastianbergmann/phpunit · error · DuplicateMethodException
Cannot double using a method list that contains duplicates:
Error message
Cannot double using a method list that contains duplicates: "%s" (duplicate: "%s")
What it means
Thrown by Generator::ensureValidMethods() when the method list for a test double fails the $methods !== array_unique($methods) check, i.e. the same method name appears twice. PHPUnit refuses to generate a double whose method list has duplicates because the generated class would define colliding methods.
Source
Thrown at src/Framework/MockObject/Generator/Generator.php:720
* @param ?list<non-empty-string> $methods
*
* @throws DuplicateMethodException
* @throws InvalidMethodNameException
*/
private function ensureValidMethods(?array $methods): void
{
if ($methods === null) {
return;
}
foreach ($methods as $method) {
if (preg_match('~\A[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\z~', (string) $method) === 0) {
throw new InvalidMethodNameException((string) $method);
}
}
if ($methods !== array_unique($methods)) {
throw new DuplicateMethodException($methods);
}
}
/**
* @throws InvalidClassNameException
*/
private function ensureValidNameForTestDoubleClass(string $className): void
{
if ($className === '') {
return;
}
if (preg_match('~\A[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\z~', $className) === 0) {
throw new InvalidClassNameException($className);
}
}
/**View on GitHub (pinned to f123cdb2a2)
Solutions
- Remove the duplicate entry reported in the message (the message names both the list and the duplicate).
- If merging lists dynamically, wrap with array_values(array_unique($methods)) before passing to onlyMethods()/addMethods().
- Check you did not pass the same method via both onlyMethods() and addMethods() on the same MockBuilder.
Example fix
// before
$mock = $this->getMockBuilder(C::class)
->onlyMethods(['load', 'save', 'load'])
->getMock();
// after
$mock = $this->getMockBuilder(C::class)
->onlyMethods(['load', 'save'])
->getMock(); Defensive patterns
Strategy: validation
Validate before calling
$methods = array_values(array_unique($methods));
if (count($methods) !== count(array_unique($methods))) {
throw new InvalidArgumentException('duplicates in method list');
} Type guard
function hasNoDuplicates(array $methods): bool
{
return count($methods) === count(array_unique($methods));
} Try / catch
try {
$mock = $builder->onlyMethods($methods)->getMock();
} catch (PHPUnit\Framework\MockObject\DuplicateMethodException $e) {
// deduplicate and retry with array_values(array_unique($methods))
} Prevention
- Deduplicate every dynamically merged method list before passing it to onlyMethods()/addMethods().
- Do not list the same method through both onlyMethods() and addMethods() on one builder.
- Keep method lists short and literal in tests; long merged arrays are the usual culprit.
When it happens
Trigger: onlyMethods(['foo', 'foo']) or addMethods(['bar', 'bar']); merging two arrays for the method list where the same name occurs in both, e.g. ->onlyMethods(array_merge($baseMethods, $extraMethods)) with overlapping entries; a data provider that repeats a name.
Common situations: Combining a base list of mocked methods with an extra list and forgetting to deduplicate; copy-paste duplication inside a long onlyMethods() array; lists assembled from multiple sources (config + hardcoded) in test helpers.
Related errors
- Cannot double method with invalid name "%s"
- Cannot use "%s" as the name of a test double class because i
- The name "%s" is already in use
- Trying to configure method "%s" which cannot be configured b
- Method %s may not return value of type %s, its declared retu
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/4fa83d593bdf1d35.
Report an issue: GitHub.