PHPackages                             christopheraue/phpspy - 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. christopheraue/phpspy

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

christopheraue/phpspy
=====================

A test spy tracking calls to methods.

0.7.0(12y ago)29133MITPHPPHP &gt;=5.3.0

Since May 11Pushed 12y ago7 watchersCompare

[ Source](https://github.com/christopheraue/phpspy)[ Packagist](https://packagist.org/packages/christopheraue/phpspy)[ Docs](https://github.com/christopheraue/phpspy)[ RSS](/packages/christopheraue-phpspy/feed)WikiDiscussions master Synced 3w ago

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

PHP Spy
=======

[](#php-spy)

Track arguments and return values of calls to functions and methods when you cannot use PHPUnit Mocks. Spies do not interfere with the behavior of the code and delegate calls to the actual implementation of the spied on function by default. But, they can be configured to delegate calls to another function.

Requirements
------------

[](#requirements)

- PHP &gt; 5.3
- [runkit](https://github.com/zenovich/runkit)

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

[](#installation)

### Via Composer

[](#via-composer)

Add to your *composer.json*:

```
{
    "require": {
        "christopheraue/phpspy": "*"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/christopheraue/phpspy"
        }
    ]
}
```

Usage
-----

[](#usage)

### Spying

[](#spying)

#### On functions

[](#on-functions)

```
function id($in)
{
    return $in;
}

$spy = new \christopheraue\phpspy\Spy("id");

id(1);
id(2);
id(3);

echo $spy->getCallCount();           //3
echo $spy->getCall->getArgCount();   //1
echo $spy->getCall(1)->getResult();  //2
echo $spy->getCall(0)->getContext(); //null
```

#### On methods

[](#on-methods)

```
class VIP
{
    private $_secret;

    public function learnSecret($secret)
    {
        $this->_secret = $secret;
    }
}
$vip = new VIP();

$spy = new \christopheraue\phpspy\Spy("VIP", "learnSecret");

$vip->learnSecret("The cake is a lie.");

echo $spy->getCallCount();           //1
echo $spy->getCall(0)->getArg(0);    //"The cake is a lie."
echo $spy->getCall(0)->getContext(); //$vip
```

#### On static methods

[](#on-static-methods)

```
class VIP
{
    public static function id($in)
    {
        return $in;
    }
}

$spy = new \christopheraue\phpspy\Spy("VIP", "id");

VIP::id("static, static, static.");

echo $spy->getCallCount();           //1
echo $spy->getCall(0)->getResult();  //"static, static, static."
echo $spy->getCall(0)->getContext(); //"VIP"
```

### Stubbing

[](#stubbing)

Calls can be intercepted by giving the spy a substitute to execute instead. They are still tracked in this case. It works for functions and methods alike.

```
function id($in)
{
    return $in;
}

$spy = new \christopheraue\phpspy\Spy("id");

//substitute for an anonymous function
$spy->actAs(function($in) {
    //do something
});

//substitute for another function
$spy->actAs('functionName');

//substitute for a method
$spy->actAs(array($object, 'method'));

//call through again
$spy->actNaturally();
```

All callables qualify as valid substitute. Anonymous functions are executed in the context of the methods they are replacing. This means

- access to the scope resolution operator (`::`) using `parent`, `self` and `static`.
- For objects, `$this` is defined and is pointing to the instance.

Complete API
------------

[](#complete-api)

### Constructor

[](#constructor)

To spy on

- (static) methods: `new \christopheraue\phpspy\Spy($className, $methodName)`
- functions: `new \christopheraue\phpspy\Spy($functionName)`

### Interface of a spy:

[](#interface-of-a-spy)

- `getCallCount()`: Returns the number of recorded calls.
- `getCall($n)`: Returns the nth recorded call. Negative $n get calls from the back of the list.
- `reset()`: Resets the spy by deleting all recorded calls.
- `actAs($callable)`: Delegates calls to a spied on function to another [callable](http://php.net/manual/en/language.types.callable.php).
- `actNaturally()`: Delegates calls to the actual implementation of the spied on function (again).
- `callOriginal($args = array(), $instance = null)`: Calls the original function without tracking the call. Arguments can be passed to the original function by passing an array with them as first argument. If the original function is a non-static method the second argument must carry the instance in which context it will be called.
- `kill()`: Deletes all recorded calls, stops recording further calls and kills the spy.

### Interface of a call:

[](#interface-of-a-call)

- `getArgCount()`: Returns the number of recorded arguments
- `getArg($n)`: Returns the nth argument of the call. Negative $n get arguments from the back of the list.
- `getResult()`: Returns the return value of the call.
- `getContext()`: Returns `null` for functions, an reference to the object for methods and the class name for static methods.

###  Health Score

27

—

LowBetter than 47% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 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 ~9 days

Total

7

Last Release

4382d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9172ff0b608d5048a144660253c740589b3d26916044bc3524af92e34fa77604?d=identicon)[christopheraue](/maintainers/christopheraue)

---

Top Contributors

[![christopheraue](https://avatars.githubusercontent.com/u/687174?v=4)](https://github.com/christopheraue "christopheraue (36 commits)")

###  Code Quality

TestsBehat

### Embed Badge

![Health badge](/badges/christopheraue-phpspy/health.svg)

```
[![Health](https://phpackages.com/badges/christopheraue-phpspy/health.svg)](https://phpackages.com/packages/christopheraue-phpspy)
```

###  Alternatives

[dms/phpunit-arraysubset-asserts

This package provides ArraySubset and related asserts once deprecated in PHPUnit 8

14429.2M360](/packages/dms-phpunit-arraysubset-asserts)

PHPackages © 2026

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