Removes final keywords from source code on-the-fly and allows mocking of final methods and classes

Overview

Bypass Finals

Downloads this Month Tests Latest Stable Version License

Introduction

Removes final keywords from source code on-the-fly and allows mocking of final methods and classes. It can be used together with any test tool such as PHPUnit, Mockery or Nette Tester.

Installation

The recommended way to install is through Composer:

composer require dg/bypass-finals --dev

It requires PHP version 7.1 (or 5.6 in case of release 1.1) and supports PHP up to 8.1.

Usage

Simply call this:

DG\BypassFinals::enable();

You need to enable it before the classes you want to remove the final are loaded. So call it as soon as possible, preferably right after vendor/autoload.php is loaded.

Note that final internal PHP classes like Closure cannot be mocked.

You can choose to only bypass finals in specific files or directories:

DG\BypassFinals::setWhitelist([
    '*/Nette/*',
]);

This gives you finer control and can solve issues with certain frameworks and libraries.

You can try to increase performance by using the cache (the directory must exist):

DG\BypassFinals::$cacheDir = __DIR__ . '/tmp';

Support Project

Do you like BypassFinals?

Donate

Comments
  • Using Infection library fails because of another stream wrapper

    Using Infection library fails because of another stream wrapper

    The library Infection uses its own stream wrapper, see \Infection\StreamWrapper\IncludeInterceptor.

    Because of that, the mutants created by the library are not used and that makes the whole library unusable if the tests use bypass-finals, because the stream wrapper is overriden.

    I tried to guess how both stream wrappers could be used alongside each other but as I have no expertise at all in this topic it got hard very fast.

    Do you think this could be possible? How could it be done? Can I help 🙂 ?

    opened by romm 19
  • Using is_file() with PHP 8.0

    Using is_file() with PHP 8.0

    Hi, Is it possible that this package isn't ready for PHP 8.0 yet? I have problem using is_file() function. It executes url_stat(), which uses @$this->native(...), and when the file doesn't exist it throw some exception that is impossible to catch by try-catch block: "stat(): stat failed for 'filename'"

    opened by PierwszyTV 8
  • Add setWhitelist method to allow controlling which files get replaced.

    Add setWhitelist method to allow controlling which files get replaced.

    Reason behind this feature: Some frameworks stop working because of DIR and such, since the files are now served from tmp. This prompted me to add a more fine-grained control.

    I added a test and documentation. The old behavior remains unaffected.

    opened by afilina 8
  • Segmentation fault with 1.4.0 when running phpunit with code coverage

    Segmentation fault with 1.4.0 when running phpunit with code coverage

    After upgrading to version 1.4.0 I get an error when running this command:

    php -dxdebug.mode=coverage bin/phpunit

    The error:

    PHPUnit 9.5.24 #StandWithUkraine
    
    Testing 
    .Segmentation fault
    

    This only occurs on 1.4.0, with version 1.3.1 everything works fine.

    opened by svnldwg 6
  • Respect final as literals

    Respect final as literals

    An idea is that only final followed by class or function is the keyword to remove. If followed by = (constant assigning value) or ( (method signature) it is a literal.

    opened by milo 6
  • [BUG] Warning thrown by `url_stat` when file does not exist

    [BUG] Warning thrown by `url_stat` when file does not exist

    When \DG\BypassFinals::url_stat is called with the path of a file that does not exist on the filesystem, a warning is thrown: stat(): stat failed for /path/to/my/unexisting/file.

    A check should be done before calling the native method with an invalid path.

    opened by romm 6
  • fix: allow using alternative stream handlers (Infection)

    fix: allow using alternative stream handlers (Infection)

    This is a PR from comments made by @dg and @maks-rafalko in #9. It's confirmed to fix issues with using Infection and BypassFinals together, tested on two of my projects.

    opened by dkarlovi 5
  • Bugfix: Make sure to restore the stream wrapper even when an exception is thrown

    Bugfix: Make sure to restore the stream wrapper even when an exception is thrown

    If a native function throws an exception, then we will not restore the stream wrapper. With this patch we will throw the exception AND restore the stream wrapper.

    To reproduce:

    BypassFinals::enable();
    
    $customHandler = static function ($type, $msg, $file, $line) {
        throw new \ErrorException($msg, 0, $type, $file, $line);
    };
    set_error_handler($customHandler);
    
    new Foo(); // This is rewritten
    try {
        include 'non/existing/path.php';
    } finally {
        restore_error_handler();
    }
    
    new Bar(); // This is still final!
    

    It took me a good 2 hours to find this bug =)

    opened by Nyholm 5
  • Updated stream_set_option signature

    Updated stream_set_option signature

    The third argument has to be nullable. While the docs specify a signature lof public streamWrapper::stream_set_option ( int $option , int $arg1 , int $arg2 ) : bool they also say this: arg2: If option is STREAM_OPTION_BLOCKING: This option is not set.

    The third argument has to be nullable. While the docs specify a signature lof public streamWrapper::stream_set_option ( int $option , int $arg1 , int $arg2 ) : bool they also say this: arg2: If option is STREAM_OPTION_BLOCKING: This option is not set.

    We get errors like this TypeError: Argument 3 passed to DG\BypassFinals::stream_set_option() must be of the type int, null given because of this.

    opened by bzikarsky 4
  • Failed infection test if bypass-final is enabled

    Failed infection test if bypass-final is enabled

    Hello, I am using the library for infection testing https://infection.github.io/guide/ and if the bypass-final library is enabled the infections are not working as expected - the coverage test is not working properly. example; the case where bypass is disabled; 100% coverage of infection

    the case where the bypass is enabled; 20-30% coverage.

    Could you please take a look at what might be wrong?

    opened by Pablossoo 3
  • The class \Closure is marked final and its methods cannot be replaced.

    The class \Closure is marked final and its methods cannot be replaced.

    Other final classes mocked sucessfully. But \Closure from PHP core don't mocked =(

    https://www.php.net/manual/en/class.closure.php

        public function test() {
           BypassFinals::enable(
           Mockery::mock(\Closure::class)
        }
    
    Mockery\Exception: The class \Closure is marked final and its methods cannot be replaced. Classes marked final can be passed in to \Mockery::mock() as instantiated objects to create a partial mock, but only if the mock is not subject to type hinting checks.
    
    /var/www/app/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php:332
    /var/www/app/vendor/mockery/mockery/library/Mockery/Generator/MockConfiguration.php:434
    /var/www/app/vendor/mockery/mockery/library/Mockery/Generator/StringManipulationGenerator.php:74
    /var/www/app/vendor/mockery/mockery/library/Mockery/Generator/CachingGenerator.php:40
    /var/www/app/vendor/mockery/mockery/library/Mockery/Container.php:221
    /var/www/app/vendor/mockery/mockery/library/Mockery.php:114
    
        public function test() {
           BypassFinals::enable(
           $this->createMock(\Closure::class);
        }
    
    Class "Closure" is declared "final" and cannot be mocked.
    
    composer info | grep dg
    
    dg/bypass-finals                                 v1.2.1                                Removes final keyword from source code on-the-fly and allows moc...
    
    composer info | grep phpunit
    
    phpunit/php-code-coverage                        8.0.2                                 Library that provides collection, processing, and rendering func...
    phpunit/php-file-iterator                        3.0.4                                 FilterIterator implementation that filters files based on a list...
    phpunit/php-invoker                              3.0.2                                 Invoke callables with a timeout
    phpunit/php-text-template                        2.0.2                                 Simple template engine.
    phpunit/php-timer                                3.1.4                                 Utility class for timing
    phpunit/php-token-stream                         4.0.3                                 Wrapper around PHP's tokenizer extension.
    phpunit/phpunit                                  9.1.5                                 The PHP Unit Testing framework.
    rregeer/phpunit-coverage-check                   0.3.1                                 Check the code coverage using the clover report of phpunit
    
    php -v
    
    PHP 7.4.3 (cli) (built: Feb 18 2020 11:53:05) ( NTS )
    Copyright (c) The PHP Group
    Zend Engine v3.4.0, Copyright (c) Zend Technologies
        with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies
        with Xdebug v2.9.2, Copyright (c) 2002-2020, by Derick Rethans
    
    opened by 4n70w4 3
Releases(v1.4.0)
Owner
David Grudl
Founder of @nette framework
David Grudl
A PHP library for mocking date and time in tests

ClockMock Slope s.r.l. ClockMock provides a way for mocking the current timestamp used by PHP for \DateTime(Immutable) objects and date/time related f

Slope 44 Dec 7, 2022
PHP Mocking Framework

Phake Phake is a framework for PHP that aims to provide mock objects, test doubles and method stubs. Phake was inspired by a lack of flexibility and e

Phake 469 Dec 2, 2022
Highly opinionated mocking framework for PHP 5.3+

Prophecy Prophecy is a highly opinionated yet very powerful and flexible PHP object mocking framework. Though initially it was created to fulfil phpsp

PHPSpec Framework 8.5k Jan 3, 2023
Add mocking capabilities to Pest or PHPUnit

This repository contains the Pest Plugin Mock. The Mocking API can be used in regular PHPUnit projects. For that, you just have to run the following c

PEST 16 Dec 3, 2022
PHP Mocking Framework

Phake Phake is a framework for PHP that aims to provide mock objects, test doubles and method stubs. Phake was inspired by a lack of flexibility and e

Phake 469 Dec 2, 2022
Package for unit testing Laravel form request classes

Package for unit testing Laravel form request classes. Why Colin DeCarlo gave a talk on Laracon online 21 about unit testing Laravel form requests cla

null 18 Dec 11, 2022
Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slowness of constantly restarting the testing environment.

Magic Test for Laravel Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slownes

null 400 Jan 5, 2023
Allows the running of PHPUnit within ExpressionEngine

EE Unit Tests EE Unit Tests is an Add-on for ExpressionEngine that allows developers to execute unit tests from the Command Line. EE Unit Tests uses P

Eric Lamb 6 Jan 14, 2022
Allows DataObjects to self-populate intelligently with fake data

Mock DataObjects for SilverStripe This module provides intelligent content generation functionality to all DataObjects. The object introspects its fie

Aaron Carlino 18 Oct 29, 2017
Library that provides collection, processing, and rendering functionality for PHP code coverage information.

phpunit/php-code-coverage Provides collection, processing, and rendering functionality for PHP code coverage information. Installation You can add thi

Sebastian Bergmann 8.5k Jan 5, 2023
CommandHelper - is a very useful thing for quick code testing and more!

CommandHelper CommandHelper - is a very useful thing for quick code testing and more! Examples: Code: require_once('commandhelper.php');

RuvSleep 1 Feb 11, 2022
An effort to make testing PHP code as easy and fun as its JavaScript equivalent

An effort to make testing PHP code as easy and fun as its JavaScript equivalent when using the excellent Jasmine, from which syntax and general usage is shamelessly borrowed.

Johan Stenqvist 24 Apr 22, 2022
Infrastructure and testing helpers for creating CQRS and event sourced applications.

Broadway is a project providing infrastructure and testing helpers for creating CQRS and event sourced applications. Broadway tries hard to not get in your way.

null 1.5k Dec 30, 2022
The modern, simple and intuitive PHP unit testing framework.

atoum PHP version atoum version 5.3 -> 5.6 1.x -> 3.x 7.2 -> 8.x 4.x (current) A simple, modern and intuitive unit testing framework for PHP! Just lik

atoum 1.4k Nov 29, 2022
:heavy_check_mark: PHP Test Framework for Freedom, Truth, and Justice

Kahlan is a full-featured Unit & BDD test framework a la RSpec/JSpec which uses a describe-it syntax and moves testing in PHP one step forward. Kahlan

Kahlan 1.1k Jan 2, 2023
PHP unit testing framework with built in mocks and stubs. Runs in the browser, or via the command line.

Enhance PHP A unit testing framework with mocks and stubs. Built for PHP, in PHP! Quick Start: Just add EnhanceTestFramework.php and you are ready to

Enhance PHP 67 Sep 12, 2022
A PHP Module, that help with geneting of task script for playwright and send it node.js

A PHP Module, that help with geneting of task script for playwright and send it node.js

LuKa 13 Dec 7, 2022
Some shorthand functions for skipping and focusing tests.

Pest Plugin: Shorthands This repository contains the Pest Plugin Shorthands. If you want to start testing your application with Pest, visit the main P

Thomas Le Duc 10 Jun 24, 2022