PHPackages                             net-tools/phpunit-given - 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. net-tools/phpunit-given

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

net-tools/phpunit-given
=======================

An alternative to PHPUnit's ReturnValueMap and ReturnCallback. A convenient solution to migrate from Prophecy.

1.0.6(3mo ago)010[1 PRs](https://github.com/net-tools/phpunit-given/pulls)BSD-3-ClausePHPPHP &gt;=8.0

Since Jul 12Pushed 3mo agoCompare

[ Source](https://github.com/net-tools/phpunit-given)[ Packagist](https://packagist.org/packages/net-tools/phpunit-given)[ Docs](https://github.com/olvlvl/phpunit-given)[ RSS](/packages/net-tools-phpunit-given/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (8)Used By (0)

olvlvl/phpunit-given
====================

[](#olvlvlphpunit-given)

[![Packagist](https://camo.githubusercontent.com/6d4bffd3d47a563c3a453ae61f60d8c721accdcf0c9705153892e5564377861e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6f6c766c766c2f706870756e69742d676976656e2e737667)](https://packagist.org/packages/olvlvl/phpunit-given)[![Code Quality](https://camo.githubusercontent.com/949431f528d982edb283615832cee326febb0fa81aeceac300a84e131eac0c7d/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f6f6c766c766c2f706870756e69742d676976656e2e737667)](https://scrutinizer-ci.com/g/olvlvl/phpunit-given)[![Code Coverage](https://camo.githubusercontent.com/1f7ddf80457b6140d50d3bb385cfa4fbd632b625a6def159dd622ba6252cf232/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6f6c766c766c2f706870756e69742d676976656e2e737667)](https://coveralls.io/r/olvlvl/phpunit-given)[![Downloads](https://camo.githubusercontent.com/0a6d5e83cc18a256f29cf0aa14292cb1b40d88f889e599095a24957c82750153/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6f6c766c766c2f706870756e69742d676976656e2e737667)](https://packagist.org/packages/olvlvl/phpunit-given)

*olvlvl/phpunit-given* provides an alternative to [PHPUnit](https://phpunit.de/)'s [ReturnValueMap](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php) and [ReturnCallback](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnCallback.php), as well as a convenient solution to migrate from [Prophecy](https://github.com/phpspec/prophecy/).

#### Disclaimer

[](#disclaimer)

In most cases `ReturnCallback` with `match` can be used effectively. Don't use this package if you're comfortable with these and don't need extra features.

#### Usage

[](#usage)

This is a simple example, more [use cases](#use-cases) below.

```
use olvlvl\Given\GivenTrait;
use PHPUnit\Framework\TestCase;

final class IntegerNameTest extends TestCase
{
    use GivenTrait; // createMock(IntegerName::class);
        $mock->method('name')->will($this
            ->given(new Integer(6))->return("six")
            ->given(new Integer(12))->return("twelve")
            ->default()->throw(LogicException::class)
        );

        $this->assertEquals("six", $mock->name(new Integer(6)));
        $this->assertEquals("twelve", $mock->name(new Integer(12)));

        $this->expectException(LogicException::class);
        $mock->name(new Integer(99));
    }
}
```

#### Installation

[](#installation)

```
composer require olvlvl/phpunit-given
```

Motivation
----------

[](#motivation)

Coming from [Prophecy](https://github.com/phpspec/prophecy/), C# Moq, [Golang Mock](https://github.com/golang/mock), or [Kotlin Mockk](https://mockk.io/), one would expect at least one of the following examples to work, but they do not.

```
$mock = $this->createMock(IntegerName::class);
$mock
    ->method('name')
    ->with(new Integer(6))
    ->willReturn("six");
$mock
    ->method('name')
    ->with(new Integer(12))
    ->willReturn("twelve");

// the next line crashes with: Expectation failed
$this->assertEquals("six", $mock->name(new Integer(6)));
```

```
$mock = $this->createMock(IntegerName::class);
$mock
    ->method('name')
    ->with(new Integer(6))->willReturn("six");
    // the next line crashes with: Method parameters already configured
    ->with(new Integer(12))->willReturn("twelve");

$this->assertEquals("six", $mock->name(new Integer(6)));
```

To return a value given certain arguments, one is expected to use [ReturnValueMap](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php) or [ReturnCallback](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnCallback.php). `ReturnValueMap` seems simple enough, but because it looks for [exact matches](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php#L40) it fails when objects are included in the arguments, unless they are the same instances. Besides, `ReturnValueMap` does not support constraints, you can forget doing anything fancy with it. That leaves us with `ReturnCallback`, which can be used effectively with `match` but requires the introduction of logic in the test, [a practice that is discouraged](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-best-practices#avoid-logic-in-tests).

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->willReturnCallback(fn (Integer $int) => match ($int) {
    new Integer(6) => 'six',
    new Integer(12) => 'twelve',
    default => throw new Exception
}));
```

My motivation creating *olvlvl/phpunit-given*, is to have an alternative to [ReturnValueMap](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php) and [ReturnCallback](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnCallback.php), that looks similar to what we find in other testing frameworks, and that allows easy migration from [Prophecy](https://github.com/phpspec/prophecy/).

Some PHPUnit issues, for reference:

- [Feature similar to withConsecutive(), but without checking order](https://github.com/sebastianbergmann/phpunit/issues/4026)
- [Improvements on withConsecutive with return](https://github.com/sebastianbergmann/phpunit/issues/4255)
- [Remove withConsecutive()](https://github.com/sebastianbergmann/phpunit/issues/4565)

Use cases
---------

[](#use-cases)

### Comparing objects

[](#comparing-objects)

[ReturnValueMap](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php) doesn't work with objects because it [uses strict equality when comparing arguments](https://github.com/sebastianbergmann/phpunit/blob/39efa00da7afd8460975f8532eb2687288472c27/src/Framework/MockObject/Stub/ReturnValueMap.php#L40). The following code throws a `TypeError` exception because `ReturnValueMap` cannot find a match and defaults to a `null` value.

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->will($this->returnValueMap([
    [ new Integer(6), "six" ],
    [ new Integer(12), "twelve" ],
]));

$mock->name(new Integer(6)); // throws TypeError
```

*olvlvl/phpunit-given* substitutes values with `Assert::equalTo()` and compares arguments using constraints. Having objects in the arguments is not a problem.

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->will($this
    ->given(new Integer(6))->return("six")
    ->given(new Integer(12))->return("twelve")
);

$this->assertEquals("six", $mock->name(new Integer(6)));
$this->assertEquals("twelve", $mock->name(new Integer(12)));
```

**Note:** You can use `Assert::identicalTo()` to check for the same instance.

### Using constraints

[](#using-constraints)

We established that values are substituted with `Assert::equalTo()` internally. Instead of values, you can also use constraints:

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->will($this
    ->given(Assert::lessThan(new Integer(6)))->return('too small')
    ->given(Assert::greaterThan(new Integer(9)))->return('too big')
    ->default()->return('just right') // `default()` is a shortcut for `given(Assert::anything())`
);

$this->assertEquals("too small", $mock->name(new Integer(5)));
$this->assertEquals("too big", $mock->name(new Integer(10)));
$this->assertEquals("just right", $mock->name(new Integer(6)));
$this->assertEquals("just right", $mock->name(new Integer(9)));
```

Of course, you could use `ReturnCallback`, although it adds logic to the test. Use whatever you feel more comfortable with.

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->willReturnCallback(fn (Integer $int) => match (true) {
    $int < new Integer(6) => 'too small',
    $int > new Integer(9) => 'too big',
    default => 'just right';
}));
```

### Migrating from Prophecy

[](#migrating-from-prophecy)

*olvlvl/phpunit-given* is a convenient solution to migrate from Prophecy because the code is quite similar:

```
$container = $this->prophesize(ContainerInterface::class);
$container->has('serviceA')->willReturn(true);
$container->has('serviceB')->willReturn(false);
```

```
$container = $this->createMock(ContainerInterface::class);
$container->method('has')->will($this
    ->given('serviceA')->return(true)
    ->given('serviceB')->return(false)
);
```

`throw()` is an alternative to `willThrow()`, and you can mismatch `return()` and `throw()`:

```
$container = $this->prophesize(ContainerInterface::class);
$container->get('serviceA')->willReturn($serviceA);
$container->get('serviceB')->willThrow(new LogicException());
```

```
$container = $this->createMock(ContainerInterface::class);
$container->method('get')->will($this
    ->given('serviceA')->return($serviceA)
    ->given('serviceB')->throw(LogicException::class)
);
```

Contrary to Prophecy, *olvlvl/phpunit-given* does not return `null` by default, instead it throws an exception:

```
$mock = $this->createMock(IntegerName::class);
$mock->method('name')->will($this
    ->given(new Integer(6))->return("six")
    ->given(new Integer(12))->return("twelve")
);

$mock->name(new Integer(13)); // throws an exception
```

```
LogicException : Unexpected invocation: Test\olvlvl\Given\Acme\IntegerName::name(Test\olvlvl\Given\Acme\Integer Object (...)): string, didn't match any of the constraints: [ [ is equal to Test\olvlvl\Given\Acme\Integer Object &000000000000000c0000000000000000 (
'value' => 6
) ], [ is equal to Test\olvlvl\Given\Acme\Integer Object &00000000000001af0000000000000000 (
'value' => 12
) ] ]

```

---

Continuous Integration
----------------------

[](#continuous-integration)

The project is continuously tested by [GitHub actions](https://github.com/olvlvl/phpunit-given/actions).

[![Tests](https://github.com/olvlvl/phpunit-given/workflows/test/badge.svg?branch=main)](https://github.com/olvlvl/phpunit-given/actions?query=workflow%3Atest)[![Static Analysis](https://github.com/olvlvl/phpunit-given/workflows/static-analysis/badge.svg?branch=main)](https://github.com/olvlvl/phpunit-given/actions?query=workflow%3Astatic-analysis)[![Code Style](https://github.com/olvlvl/phpunit-given/workflows/code-style/badge.svg?branch=main)](https://github.com/olvlvl/phpunit-given/actions?query=workflow%3Acode-style)

Code of Conduct
---------------

[](#code-of-conduct)

This project adheres to a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

License
-------

[](#license)

**olvlvl/phpunit-given** is released under the [BSD-3-Clause](LICENSE).

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance81

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 85.7% 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 ~157 days

Recently: every ~235 days

Total

7

Last Release

101d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2cb0c1d404c8ae72b0a731246130079c2f440d6ea079815ca8c153aa361b1f28?d=identicon)[nettools.ovh](/maintainers/nettools.ovh)

---

Top Contributors

[![net-tools](https://avatars.githubusercontent.com/u/6818724?v=4)](https://github.com/net-tools "net-tools (6 commits)")[![olvlvl](https://avatars.githubusercontent.com/u/155998?v=4)](https://github.com/olvlvl "olvlvl (1 commits)")

---

Tags

phpunitmocktest double

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/net-tools-phpunit-given/health.svg)

```
[![Health](https://phpackages.com/badges/net-tools-phpunit-given/health.svg)](https://phpackages.com/packages/net-tools-phpunit-given)
```

###  Alternatives

[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k497.0M23.6k](/packages/mockery-mockery)[brianium/paratest

Parallel testing for PHP

2.5k118.8M754](/packages/brianium-paratest)[php-mock/php-mock-phpunit

Mock built-in PHP functions (e.g. time()) with PHPUnit. This package relies on PHP's namespace fallback policy. No further extension is needed.

1718.2M399](/packages/php-mock-php-mock-phpunit)[blastcloud/guzzler

Supercharge your app or SDK with a testing library specifically for Guzzle.

272419.3k35](/packages/blastcloud-guzzler)[lastzero/test-tools

Increases testing productivity by adding a service container and self-initializing fakes to PHPUnit

2244.3k13](/packages/lastzero-test-tools)[colinodell/psr-testlogger

PSR-3 compliant test logger based on psr/log v1's, but compatible with v2 and v3 too!

1712.1M47](/packages/colinodell-psr-testlogger)

PHPackages © 2026

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