sebastianbergmann/phpunit · error · RuntimeException
At least two interfaces must be specified
Error message
At least two interfaces must be specified
What it means
createMockForIntersectionOfInterfaces()/createStubForIntersectionOfInterfaces() build a test double that satisfies the intersection of several interfaces at once (PHP does not allow runtime intersection types, so PHPUnit generates a named intersection interface). At least two interfaces are required for an intersection to be meaningful; passing fewer causes this RuntimeException.
Source
Thrown at src/Framework/MockObject/Generator/Generator.php:144
if ($mockObject) {
assert($object instanceof MockObject);
} else {
assert($object instanceof Stub);
}
return $object;
}
/**
* @param list<class-string> $interfaces
*
* @throws RuntimeException
* @throws UnknownInterfaceException
*/
public function testDoubleForInterfaceIntersection(array $interfaces, bool $mockObject, bool $returnValueGeneration = true): MockObject|Stub
{
if (count($interfaces) < 2) {
throw new RuntimeException('At least two interfaces must be specified');
}
foreach ($interfaces as $interface) {
if (!interface_exists($interface)) {
throw new UnknownInterfaceException($interface);
}
}
sort($interfaces);
$methods = [];
foreach ($interfaces as $interface) {
$methods = array_merge($methods, $this->namesOfMethodsIn($interface));
}
if (count(array_unique($methods)) < count($methods)) {
throw new RuntimeException('Interfaces must not declare the same method');View on GitHub (pinned to f123cdb2a2)
Solutions
- Pass at least two existing interfaces: createMockForIntersectionOfInterfaces([A::class, B::class])
- If only one interface is needed, use createMock(A::class) instead
- When the list is computed, guard it: if (count($interfaces) < 2) { return createMock($interfaces[0]); }
Example fix
// before
$registry = $this->createMockForIntersectionOfInterfaces(
[CacheInterface::class] // only one
);
// after
$registry = $this->createMockForIntersectionOfInterfaces(
[CacheInterface::class, LoggerInterface::class]
);
// or, if one suffices:
$registry = $this->createMock(CacheInterface::class); Defensive patterns
Strategy: validation
Validate before calling
if (count($interfaces) < 2) {
// Not an intersection: fall back to a plain mock
$double = $this->createMock($interfaces[0]);
} else {
$double = $this->createMockForIntersectionOfInterfaces($interfaces);
} Prevention
- Use intersection mocks only when two or more interfaces are genuinely required together
- For dynamically built interface lists, assert count >= 2 in a data-provider guard before the test body
When it happens
Trigger: createMockForIntersectionOfInterfaces([SessionHandlerInterface::class]) with a single element, an empty array, or a list where a dynamic/computed list collapsed to one entry (e.g. array_filter removed the second interface, config returned one).
Common situations: Test data built dynamically from configuration or parametrized providers where the second interface is optional and sometimes absent; refactoring from a hand-written combined interface to intersection mocks; copy-paste leftovers where one interface was commented out.
Related errors
- Interface "%s" does not exist
- Interfaces must not declare the same method
- Class "%s" is an anonymous class and cannot be doubled
- Class "%s" is an enumeration and cannot be doubled
- Class "%s" is declared "final" and cannot be doubled
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/b0ff732c309a2f55.
Report an issue: GitHub.