Skip to content

Commit

Permalink
Update codebase to PHP 7.4 (#197)
Browse files Browse the repository at this point in the history
* Update codebase to PHP 7.4

* Update docs

* Fix review comments
  • Loading branch information
TavoNiievez authored Dec 4, 2021
1 parent 124fa59 commit 345dff6
Show file tree
Hide file tree
Showing 33 changed files with 430 additions and 508 deletions.
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ AspectMock allows you to stub and mock practically anything in your PHP code!

**Documentation** | [Test Doubles Builder](https://github.com/Codeception/AspectMock/blob/master/docs/Test.md) | [ClassProxy](https://github.com/Codeception/AspectMock/blob/master/docs/ClassProxy.md) | [InstanceProxy](https://github.com/Codeception/AspectMock/blob/master/docs/InstanceProxy.md) | [FuncProxy](https://github.com/Codeception/AspectMock/blob/master/docs/FuncProxy.md)

[![Build Status](https://travis-ci.org/Codeception/AspectMock.png?branch=master)](https://travis-ci.org/Codeception/AspectMock)
[![Actions Status](https://github.com/Codeception/AspectMock/workflows/CI/badge.svg)](https://github.com/Codeception/AspectMock/actions)
[![Latest Stable Version](https://poser.pugx.org/codeception/aspect-mock/v/stable.png)](https://packagist.org/packages/codeception/aspect-mock)
[![Total Downloads](https://poser.pugx.org/codeception/aspect-mock/downloads)](https://packagist.org/packages/codeception/aspect-mock)
[![Monthly Downloads](https://poser.pugx.org/codeception/aspect-mock/d/monthly)](https://packagist.org/packages/codeception/aspect-mock)
[![PHP 7 ready](http://php7ready.timesplinter.ch/Codeception/AspectMock/master/badge.svg)](https://packagist.org/packages/codeception/aspect-mock)


## Motivation

Expand Down Expand Up @@ -45,14 +43,14 @@ Let's redefine static methods and verify their calls at runtime.

``` php
<?php

function testTableName()
{
$this->assertEquals('users', UserModel::tableName());
$userModel = test::double('UserModel', ['tableName' => 'my_users']);
$this->assertEquals('my_users', UserModel::tableName());
$userModel->verifyInvoked('tableName');
}
?>
```

#### Allows replacement of class methods.
Expand All @@ -61,14 +59,14 @@ Testing code developed with the **ActiveRecord** pattern. Does the use of the Ac

``` php
<?php

class UserService {
function createUserByName($name) {
$user = new User;
$user->setName($name);
$user->save();
}
}
?>
```

Without AspectMock you need to introduce `User` as an explicit dependency into class `UserService` to get it tested.
Expand All @@ -79,6 +77,7 @@ Instead we will replace it with a dummy and verify that it gets called by `creat

``` php
<?php

function testUserCreate()
{
$user = test::double('User', ['save' => null]);
Expand All @@ -87,13 +86,13 @@ function testUserCreate()
$this->assertEquals('davert', $user->getName());
$user->verifyInvoked('save');
}
?>
```

#### Intercept even parent class methods and magic methods

``` php
<?php

// User extends ActiveRecord
function testUserCreate()
{
Expand All @@ -105,13 +104,13 @@ function testUserCreate()
$AR->verifyInvoked('save');
$this->assertEquals('miles', $user->getName());
}
?>
```

#### Override even standard PHP functions

``` php
<?php

namespace demo;
test::func('demo', 'time', 'now');
$this->assertEquals('now', time());
Expand All @@ -123,24 +122,23 @@ Only 4 methods are necessary for method call verification and one method to defi

``` php
<?php

function testSimpleStubAndMock()
{
{
$user = test::double(new User, ['getName' => 'davert']);
$this->assertEquals('davert', $user->getName());
$user->verifyInvoked('getName');
$user->verifyInvokedOnce('getName');
$user->verifyNeverInvoked('setName');
$user->verifyInvokedMultipleTimes('setName',1);
}
?>
```

To check that method `setName` was called with `davert` as argument.

``` php
<?php
$user->verifyMethodInvoked('setName', ['davert']);
?>
```

## Wow! But how does it work?
Expand All @@ -149,7 +147,8 @@ No PECL extensions is required. The [Go! AOP](http://go.aopphp.com/) library doe

## Requirements

PHP >= 5.6 + [Go! AOP Requirements](https://github.com/goaop/framework#requirements)
* `PHP 7.4`.
* `Go! AOP 3.0`

## Installation

Expand Down Expand Up @@ -177,14 +176,14 @@ Include `AspectMock\Kernel` class into your tests bootstrap file.

``` php
<?php

include __DIR__.'/../vendor/autoload.php'; // composer autoload

$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__.'/../src']
]);
?>
```

If your project uses Composer's autoloader, that's all you need to get started.
Expand All @@ -195,6 +194,7 @@ If you use a custom autoloader (like in Yii/Yii2 frameworks), you should explici

``` php
<?php

include __DIR__.'/../vendor/autoload.php'; // composer autoload

$kernel = \AspectMock\Kernel::getInstance();
Expand All @@ -203,7 +203,6 @@ $kernel->init([
'includePaths' => [__DIR__.'/../src']
]);
$kernel->loadFile('YourAutoloader.php'); // path to your autoloader
?>
```

Load all autoloaders of your project this way, if you do not rely on Composer entirely.
Expand All @@ -217,6 +216,7 @@ Explicitly load all required files before testing:

``` php
<?php

include __DIR__.'/../vendor/autoload.php'; // composer autoload

$kernel = \AspectMock\Kernel::getInstance();
Expand All @@ -226,7 +226,6 @@ $kernel->init([
]);
require 'YourAutoloader.php';
$kernel->loadPhpFiles('/../common');
?>
```

### Customization
Expand All @@ -244,14 +243,14 @@ Example:

``` php
<?php

$kernel = \AspectMock\Kernel::getInstance();
$kernel->init([
'appDir' => __DIR__ . '/../../',
'cacheDir' => '/tmp/myapp',
'includePaths' => [__DIR__.'/../src']
'excludePaths' => [__DIR__] // tests dir should be excluded
]);
?>
```

[More configs for different frameworks](https://github.com/Codeception/AspectMock/wiki/Example-configs).
Expand All @@ -271,6 +270,7 @@ Clear the test doubles registry between tests.

``` php
<?php

use AspectMock\Test as test;

class UserTest extends \PHPUnit_Framework_TestCase
Expand All @@ -287,8 +287,6 @@ class UserTest extends \PHPUnit_Framework_TestCase
\demo\UserModel::tableName();
$user->verifyInvokedMultipleTimes('tableName',2);
}

?>
```

## Usage in Codeception.
Expand All @@ -298,6 +296,7 @@ We recommend including a call to `test::clean()` from your `CodeHelper` class:

``` php
<?php

namespace Codeception\Module;

class CodeHelper extends \Codeception\Module
Expand All @@ -307,7 +306,6 @@ class CodeHelper extends \Codeception\Module
\AspectMock\Test::clean();
}
}
?>
```

## Improvements?
Expand Down
1 change: 1 addition & 0 deletions RoboFile.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

require_once 'vendor/autoload.php';

class Robofile extends \Robo\Tasks
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "codeception/aspect-mock",
"description": "Experimental Mocking Framework powered by Aspects",
"license": "MIT",
"authors": [
{
"name": "Michael Bodnarchuk",
Expand All @@ -21,7 +22,7 @@
"require-dev": {
"codeception/codeception": "^4.1",
"codeception/verify": "^2.1",
"codeception/specify": "^1.4"
},
"license": "MIT"
"codeception/specify": "^1.4",
"consolidation/robo": "^3.0"
}
}
58 changes: 12 additions & 46 deletions docs/ClassProxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,22 @@ ClassProxy represents a class of your project.
* It can be used to check class definitions.


``` php
```php
<?php
$userModel = test::double('UserModel');
UserModel::tableName();
$user = $userModel->construct();
$user->save();
$userModel->verifyInvoked('tableName');
$userModel->verifyInvoked('save');
?>
```

You can get a class name of a proxy via `className` property.

``` php
```php
<?php
$userModel = test::double('UserModel');
$userModel->className; // UserModel
?>
```

Also, you can get the list of calls for a specific method.
Expand All @@ -37,65 +35,50 @@ Also, you can get the list of calls for a specific method.
$user = test::double('UserModel');
$user->someMethod('arg1', 'arg2');
$user->getCallsForMethod('someMethod') // [ ['arg1', 'arg2'] ]
?>
```

#### *public* getCallsForMethod($method)
#### *public* isDefined()
Returns true if class exists.
Returns false if class is not defined yet, and was declared via `test::spec`.

* return bool

#### *public* interfaces()
Returns an array with all interface names of a class

* return array

#### *public* parent()
Returns a name of the parent of a class.

* return null

#### *public* hasMethod($method)
* `param` $method
* return bool
* `param mixed` $method

#### *public* hasProperty($property)
* `param` $property
* return bool
* `param mixed` $property

#### *public* traits()
Returns array of all trait names of a class.

* return array

#### *public* construct()
Creates an instance of a class via constructor.

``` php
```php
<?
$user = test::double('User')->construct([
'name' => 'davert',
'email' => 'davert@mail.ua'
]);

?>
```
* return object

#### *public* make()
Creates a class instance without calling a constructor.

``` php
```php
<?
$user = test::double('User')->make();

?>
```
* return object

#### *public* verifyInvoked($name, $params = null)
#### *public* verifyInvoked($name, array $params = null)
Verifies a method was invoked at least once.
In second argument you can specify with which params method expected to be invoked;

Expand All @@ -104,38 +87,24 @@ In second argument you can specify with which params method expected to be invok
$user->verifyInvoked('save');
$user->verifyInvoked('setName',['davert']);

?>
```

* `param` $name
* `param null` $params
* throws \PHPUnit_Framework_ExpectationFailedException
* `param array` $params
* throws fail

#### *public* verifyInvokedOnce($name, $params = null)
#### *public* verifyInvokedOnce($name, array $params = null)
Verifies that method was invoked only once.

* `param` $name
* `param array` $params

#### *public* verifyInvokedMultipleTimes($name, $times, $params = null)
#### *public* verifyInvokedMultipleTimes($name, $times, array $params = null)
Verifies that method was called exactly $times times.

``` php
<?php
$user->verifyInvokedMultipleTimes('save',2);
$user->verifyInvokedMultipleTimes('dispatchEvent',3,['before_validate']);
$user->verifyInvokedMultipleTimes('dispatchEvent',4,['after_save']);
?>
```

* `param` $name
* `param` $times
* `param array` $params
* throws \PHPUnit_Framework_ExpectationFailedException
* throws ExpectationFailedException

#### *public* verifyNeverInvoked($name, $params = null)
#### *public* verifyNeverInvoked($name, array $params = null)
Verifies that method was not called.
In second argument with which arguments is not expected to be called.

Expand All @@ -146,11 +115,8 @@ $user->verifyNeverInvoked('setName'); // fail
$user->verifyNeverInvoked('setName',['davert']); // fail
$user->verifyNeverInvoked('setName',['bob']); // success
$user->verifyNeverInvoked('setName',[]); // success
?>
```

* `param` $name
* `param null` $params
* throws \PHPUnit_Framework_ExpectationFailedException
* throws ExpectationFailedException


Loading

0 comments on commit 345dff6

Please sign in to comment.