PHPackages                             jasny/phpunit-extension - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. jasny/phpunit-extension

ActiveLibrary[Testing &amp; Quality](/categories/testing)

jasny/phpunit-extension
=======================

Additional functionality for PHPUnit (callback mock, expected warning, ...)

v0.5.1(1y ago)35.5k↓73.2%[1 issues](https://github.com/jasny/phpunit-extension/issues)8MITPHPPHP &gt;=8.1CI failing

Since Sep 15Pushed 1y agoCompare

[ Source](https://github.com/jasny/phpunit-extension)[ Packagist](https://packagist.org/packages/jasny/phpunit-extension)[ RSS](/packages/jasny-phpunit-extension/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (2)Dependencies (4)Versions (12)Used By (8)

Jasny PHPUnit extension
=======================

[](#jasny-phpunit-extension)

[![Build status](https://github.com/jasny/phpunit-extension/actions/workflows/php.yml/badge.svg)](https://github.com/jasny/phpunit-extension/actions/workflows/php.yml)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/c87c6c79b94d129cad0a91530c2bfc98c18d67268de90d9b45b7275b0e7dfd35/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6a61736e792f706870756e69742d657874656e73696f6e2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/jasny/phpunit-extension/?branch=master)[![Code Coverage](https://camo.githubusercontent.com/f2d9811bc720cd3dd141d5483a2554f1a4c3e7c6bc26b2a681a1c13371b3fe76/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6a61736e792f706870756e69742d657874656e73696f6e2f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/jasny/phpunit-extension/?branch=master)[![Packagist Stable Version](https://camo.githubusercontent.com/065cbcc967e616eee817d215f13bf31aa3e91a7d5139b957b0ec0c581ba8aebe/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a61736e792f706870756e69742d657874656e73696f6e2e737667)](https://packagist.org/packages/jasny/phpunit-extension)[![Packagist License](https://camo.githubusercontent.com/073a171c4f0f2fe410babfa2c1638252c505456d7fffa0c923bf0db5dda8767e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a61736e792f706870756e69742d657874656e73696f6e2e737667)](https://packagist.org/packages/jasny/phpunit-extension)

Additional functionality for PHPUnit.

- [Callback mock](#callback-mock) - assert that callback is called with correct arguments.
- [Expected warning](#expected-warning) - assert notice/warning is triggered and continue running.
- [In context of](#in-context-of) - Access private/protected methods and properties.
- [Consecutive calls](#consecutive-calls) - Replacement for removed `withConsecutive()` method.

Installation
------------

[](#installation)

```
composer require jasny/phpunit-extension

```

Usage
-----

[](#usage)

### Callback mock

[](#callback-mock)

```
MockObject createCallbackMock(InvocationOrder $matcher, array|Closure $assert = null, $return = null)

```

The method takes either the expected arguments as array and the return value or a `Closure`. If a `Closure` is given, it will be called with an `InvocationMocker`, which can be used for more advanced matching.

```
use Jasny\PHPUnit\CallbackMockTrait;
use PHPUnit\Framework\MockObject\Builder\InvocationMocker;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use CallbackMockTrait;

    public function testSingleCall()
    {
        $callback = $this->createCallbackMock($this->once(), ['abc'], 10);
        function_that_invokes($callback);
    }

    public function testConsecutiveCalls()
    {
        $callback = $this->createCallbackMock(
            $this->exactly(2),
            function(InvocationMocker $invoke) {
                $invoke
                    ->withConsecutive(['abc'], ['xyz'])
                    ->willReturnOnConsecutiveCalls(10, 42);
            }
        );

        function_that_invokes($callback);
    }
}
```

### Safe Mocks

[](#safe-mocks)

The `SafeMocksTrait` overwrites the `createMock` method to disable auto-return value generation. This means that the test will fail if any method is called that isn't configured.

```
use Jasny\PHPUnit\SafeMocksTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use SafeMocksTrait;

    public function test()
    {
        $foo = $this->createMock(Foo::class);
        $foo->expects($this->once())->method('hello');

        $foo->hello();
        $foo->bye();
    }
}
```

In the example above, the method `bye()` isn't configured for `$foo`. Normally the test would succeed, but with `SafeMocksTrait` this test will result in the failure

```
Return value inference disabled and no expectation set up for Foo::bye()

```

### Expected warning

[](#expected-warning)

`ExpectedWarningTrait` overwrites the following methods;

- `expectNotice()`
- `expectNoticeMessage(string $message)`
- `expectNoticeMessageMatches(string $regexp)`
- `expectWarning()`
- `expectWarningMessage(string $message)`
- `expectWarningMessageMatches(string $regexp)`
- `expectDeprecation()`
- `expectDeprecationMessage(string $message)`
- `expectDeprecationMessageMatches(string $regexp)`

Take the following example function;

```
function my_old_func(float $a)
{
    trigger_error("Use my_new_func() instead", E_USER_DEPRECATED);
    return (int)($a * 100);
}
```

PHPUnit converts notices and warning to exceptions. While you can catch these exceptions through methods like `expectDeprecation`, any code after the the notice/warning isn't run and therefor untestable.

The following test succeeds, while it should fail.

```
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    public function test()
    {
        $this->expectDeprecation();

        $result = my_old_func(0.42); // assertEquals(89, $result); // This should fail, but is never executed
    }
}
```

`ExpectedWarningTrait` sets a custom error handler, that catches expected warnings and notices, without converting them to exceptions. Code will continue to run.

After all other assertions succeed, the code will check if there are any expected warnings/notices that haven't been triggered.

```
use Jasny\PHPUnit\ExpectWarningTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use ExpectWarningTrait;

    public function test()
    {
        $this->expectDeprecation();

        $result = my_old_func(0.42); // assertEquals(89, $result); // Will fail
    }
}
```

### In context of

[](#in-context-of)

```
mixed inContextOf(object $object, \Closure $function)

```

The function is called in context of the given object. This allows to call private and protected methods and get or set private and protected properties.

```
use Jasny\PHPUnit\InContextOfTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use InContextOfTrait;

    public function testCallPrivateMethod()
    {
        $object = new MyObject();

        $result = $this->inContextOf($object, fn($object) => $object->privateMethod('foo', 'bar'));
        $this->assertEquals($result, 'foo-bar');
    }

    public function testGetPrivateProperty()
    {
        $value = $this->inContextOf($object, fn($object) => $object->privateProperty);
        $this->assertEquals($value, 999);
    }

    /** Alternatively, do the assertion in the closure */
    public function testAssertPrivateProperty()
    {
        $this->inContextOf($object, fn($object) => $this->assertEquals($object->privateProperty, 999));
    }

    public function testSetPrivateProperty()
    {
        $this->inContextOf($object, fn($object) => $object->privateProperty = 42);
    }
}
```

***Beware:** You should only test via public methods and properties. When you're required to access private methods or properties to perform tests, something is likely wrong in the architecture of your code.*

### Consecutive calls

[](#consecutive-calls)

`ConsecutiveTrait` is a replacement for PHPUnit's `withConsecutive` method which was removed in PHPUnit 10.

```
use Jasny\PHPUnit\ConsecutiveTrait;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use ConsecutiveTrait;

    public function test()
    {
        $mock = $this->createMock(MyClass::class);
        $mock->expects($this->exactly(2))
            ->method('foo')
            ->with(...$this->consecutive(
                ['a', 1],
                ['b', 2],
            ))
            ->willReturnOnConsecutiveCalls(10, 42);

        $this->assertEquals(10, $mock->foo('a', 1));
        $this->assertEquals(42, $mock->foo('b', 2));
    }
}
```

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance26

Infrequent updates — may be unmaintained

Popularity26

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~241 days

Recently: every ~338 days

Total

10

Last Release

673d ago

PHP version history (5 changes)v0.1.0PHP ~7.1

v0.2.0PHP ~7.2

v0.3.0PHP &gt;=7.4

v0.3.2PHP &gt;=7.2

v0.5.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/3379a93d51305df325df9045e1a8b205d195e4e8c01312dff53a000ee79002eb?d=identicon)[jasny](/maintainers/jasny)

---

Top Contributors

[![jasny](https://avatars.githubusercontent.com/u/100821?v=4)](https://github.com/jasny "jasny (34 commits)")

---

Tags

php7phpunittesting-tools

###  Code Quality

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jasny-phpunit-extension/health.svg)

```
[![Health](https://phpackages.com/badges/jasny-phpunit-extension/health.svg)](https://phpackages.com/packages/jasny-phpunit-extension)
```

###  Alternatives

[brianium/paratest

Parallel testing for PHP

2.5k136.1M986](/packages/brianium-paratest)[drupal/core-dev

require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.

2022.6M343](/packages/drupal-core-dev)[webmozarts/strict-phpunit

Enables type-safe comparisons of objects in PHPUnit

30314.4k7](/packages/webmozarts-strict-phpunit)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
