Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 114 additions & 32 deletions docs/en/appendices/phpunit10.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# PHPUnit 10 Upgrade
# PHPUnit Migration Guide

With CakePHP 5 the minimum PHPUnit version has changed from `^8.5 || ^9.3` to `^10.1`. This introduces a few breaking changes from PHPUnit as well as from CakePHP's side.
This guide covers the PHPUnit version requirements and migration steps for CakePHP 5.x applications.

## Current Requirements

CakePHP 5.x requires **PHPUnit ^11.5.3 or ^12.1.3**. This means:

- PHPUnit 11.5.3+ requires **PHP 8.2** or later
- PHPUnit 12.1.3+ requires **PHP 8.3** or later

> [!NOTE]
> PHPUnit 10 is no longer supported in CakePHP 5.x. If you are still on PHPUnit 10,
> you must upgrade to PHPUnit 11 or 12.

## phpunit.xml adjustments

Expand All @@ -9,60 +20,131 @@ It is recommended to let PHPUnit update its configuration file via the following
vendor/bin/phpunit --migrate-configuration

> [!NOTE]
> Make sure you are already on PHPUnit 10 via `vendor/bin/phpunit --version` before executing this command!
> Make sure you verify your PHPUnit version via `vendor/bin/phpunit --version` before executing this command!

With this command out of the way your `phpunit.xml` already has most of the recommended changes present.
### Extension Configuration

### New event system
CakePHP's fixture extension uses PHPUnit's event system. Your `phpunit.xml` should have:

PHPUnit 10 removed the old hook system and introduced a new [Event system](https://docs.phpunit.de/en/10.5/extending-phpunit.html#extending-the-test-runner)
which requires the following code in your `phpunit.xml` to be adjusted from:

``` php
``` xml
<extensions>
<extension class="Cake\TestSuite\Fixture\PHPUnitExtension"/>
<bootstrap class="Cake\TestSuite\Fixture\Extension\PHPUnitExtension"/>
</extensions>
```

to:
## Migrating from PHPUnit 10 to 11

### Annotations to Attributes

PHPUnit 11 deprecates docblock annotations and PHPUnit 12 removes them entirely.
You should migrate to PHP 8 attributes:

``` php
<extensions>
<bootstrap class="Cake\TestSuite\Fixture\Extension\PHPUnitExtension"/>
</extensions>
// Old way (deprecated in PHPUnit 11, removed in PHPUnit 12)
/**
* @dataProvider myProvider
*/
public function testSomething($value): void
{
}

// New way (required for PHPUnit 12+)
use PHPUnit\Framework\Attributes\DataProvider;

#[DataProvider('myProvider')]
public function testSomething($value): void
{
}
```

## `->withConsecutive()` has been removed
Common attributes to use:

| Old Annotation | New Attribute |
|---------------|---------------|
| `@test` | `#[Test]` |
| `@dataProvider name` | `#[DataProvider('name')]` |
| `@depends methodName` | `#[Depends('methodName')]` |
| `@group name` | `#[Group('name')]` |
| `@covers ClassName` | `#[CoversClass(ClassName::class)]` |
| `@uses ClassName` | `#[UsesClass(ClassName::class)]` |

Remember to import the attribute classes from `PHPUnit\Framework\Attributes`.

You can convert the removed `->withConsecutive()` method to a
working interim solution like you can see here:
### Data Providers Must Be Static

Data provider methods must be both `public` and `static`:

``` php
->withConsecutive(['firstCallArg'], ['secondCallArg'])
// Required format
public static function myProvider(): array
{
return [
['value1'],
['value2'],
];
}
```

should be converted to:
### Test Double Changes

PHPUnit 11 made changes to mock object creation:

- **Use `createStub()`** when you only need to stub return values and don't need
to verify method calls
- **Use `createMock()`** when you need to set expectations and verify interactions

``` php
->with(
...self::withConsecutive(['firstCallArg'], ['secondCallArg'])
)
// For isolating dependencies (no expectations)
$stub = $this->createStub(SomeClass::class);
$stub->method('getValue')->willReturn('test');

// For testing object communication (with expectations)
$mock = $this->createMock(SomeClass::class);
$mock->expects($this->once())
->method('doSomething')
->with('argument');
```

the static `self::withConsecutive()` method has been added via the `Cake\TestSuite\PHPUnitConsecutiveTrait`
to the base `Cake\TestSuite\TestCase` class so you don't have to manually add that trait to your Testcase classes.
> [!WARNING]
> Configuring expectations (like `expects()`) on objects created with `createStub()`
> triggers deprecation warnings in PHPUnit 11 and errors in PHPUnit 12.

## Migrating from PHPUnit 11 to 12

PHPUnit 12 requires **PHP 8.3** or later and enforces all deprecations from PHPUnit 11:

- Docblock annotations are completely removed
- Expectations on stubs are no longer allowed
- Abstract class and trait mocking methods are removed

Run your test suite with PHPUnit 11.5 and resolve all deprecation warnings before
upgrading to PHPUnit 12.

## CakePHP Test Utilities

## data providers have to be static
### withConsecutive() Replacement

If your testcases leverage the data provider feature of PHPUnit then
you have to adjust your data providers to be static:
The removed `->withConsecutive()` method can be replaced using CakePHP's trait:

``` php
public function myProvider(): array
// Old way (removed in PHPUnit 10+)
->withConsecutive(['firstCallArg'], ['secondCallArg'])

// New way using CakePHP's trait
->with(
...self::withConsecutive(['firstCallArg'], ['secondCallArg'])
)
```

should be converted to:
The static `self::withConsecutive()` method is provided via the `Cake\TestSuite\PHPUnitConsecutiveTrait`
which is automatically included in the base `Cake\TestSuite\TestCase` class.

``` text
public static function myProvider(): array
```
## Upgrade Checklist

Before upgrading PHPUnit versions, ensure:

1. Your test suite runs without deprecation warnings on your current PHPUnit version
2. All data providers are `public static` methods
3. You're using attributes instead of annotations (required for PHPUnit 12)
4. Mock expectations are only used with `createMock()`, not `createStub()`
5. Run `vendor/bin/phpunit --migrate-configuration` after upgrading