sebastianbergmann/phpunit · error · PropertyCannotBeDoubledException
Trying to double property "%s" of class "%s" with doubleProp
Error message
Trying to double property "%s" of class "%s" with doubleProperties(), but it does not declare a type
What it means
Thrown by TestDoubleBuilder::doubleProperties() when the target property declares no type. Doubling works by redeclaring the property with generated hooks, and a hooked property in PHP must have a declared type, so PHPUnit rejects untyped properties via ReflectionProperty::hasType().
Source
Thrown at src/Framework/MockObject/TestDoubleBuilder.php:147
if (!$property->isPublic()) {
throw new PropertyCannotBeDoubledException($this->type, $propertyName, 'it is not public');
}
if ($property->isStatic()) {
throw new PropertyCannotBeDoubledException($this->type, $propertyName, 'it is static');
}
if ($property->isReadOnly()) {
throw new PropertyCannotBeDoubledException($this->type, $propertyName, 'it is readonly');
}
if ($property->isFinal()) {
throw new PropertyCannotBeDoubledException($this->type, $propertyName, 'it is final');
}
if (!$property->hasType()) {
throw new PropertyCannotBeDoubledException($this->type, $propertyName, 'it does not declare a type');
}
}
$this->doubledProperties = array_merge($this->doubledProperties, $properties);
return $this;
}
/**
* Specifies the arguments for the constructor.
*
* @param array<mixed> $arguments
*
* @return $this
*/
public function setConstructorArgs(array $arguments): static
{
$this->constructorArgs = $arguments;View on GitHub (pinned to f123cdb2a2)
Solutions
- Add a native type declaration to the property in the production class, then keep it in doubleProperties()
- Remove the untyped property from the doubling list
- If the type cannot be added, double a method that returns the value instead of the property
Example fix
// before
class Settings {
public $cache; // no type -> PropertyCannotBeDoubledException
}
// after
class Settings {
public ?array $cache = null; // typed, now doublable
} Defensive patterns
Strategy: validation
Validate before calling
$property = new ReflectionProperty(Settings::class, 'cache');
if (!$property->hasType()) {
// add a native type to Settings::$cache before doubling it
} Type guard
function isTypedProperty(string $class, string $property): bool
{
return (new ReflectionClass($class))
->getProperty($property)
->hasType();
} Prevention
- Enable strict property typing in CI (e.g. via phpstan level with property type checks) so untyped properties surface early
- Do not rely on @var docblocks for properties you intend to double
When it happens
Trigger: Calling doubleProperties([...]) with a property that has no type declaration (e.g. 'public $cache;' or a property only documented with a docblock like @var).
Common situations: Legacy classes with untyped properties or properties typed only in docblocks; migrating old tests to the new property-doubling API.
Related errors
- Trying to double property "%s" of class "%s" with doubleProp
- Trying to double property "%s" of class "%s" with doubleProp
- Cannot double method with invalid name "%s"
- Cannot double using a method list that contains duplicates:
- Cannot use "%s" as the name of a test double class because i
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/b7104d3270be00e5.
Report an issue: GitHub.