Giter VIP home page Giter VIP logo

php-mock-phpunit's Introduction

PHP-Mock: mocking built-in PHP functions

PHP-Mock is a testing library which mocks non deterministic built-in PHP functions like time() or rand(). This is achieved by PHP's namespace fallback policy:

PHP will fall back to global functions […] if a namespaced function […] does not exist.

PHP-Mock uses that feature by providing the namespaced function. I.e. you have to be in a non global namespace context and call the function unqualified:

namespace foo;

$time = time(); // This call can be mocked, a call to \time() can't.

Requirements and restrictions

  • Only unqualified function calls in a namespace context can be mocked. E.g. a call for time() in the namespace foo is mockable, a call for \time() is not.

  • The mock has to be defined before the first call to the unqualified function in the tested class. This is documented in Bug #68541. In most cases, you can ignore this restriction but if you happen to run into this issue you can call Mock::define() before that first call. This would define a side effectless namespaced function which can be enabled later. Another effective approach is running your test in an isolated process.

Alternatives

If you can't rely on or just don't want to use the namespace fallback policy, there are alternative techniques to mock built-in PHP functions:

  • PHPBuiltinMock relies on the APD extension.

  • MockFunction is a PHPUnit extension. It uses the runkit extension.

  • UOPZ is a Zend extension which allows, among others, renaming and deletion of functions.

  • vfsStream is a stream wrapper for a virtual file system. This will help you write tests which covers PHP stream functions (e.g. fread() or readdir()).

Installation

Use Composer:

composer require --dev php-mock/php-mock

Usage

You don't need to learn yet another API. PHP-Mock has integrations for these testing frameworks:

Note: If you plan to use one of the above mentioned testing frameworks you can skip reading any further and just go to the particular integration project.

PHP-Mock API

You find the API in the namespace phpmock.

Create a Mock object. You can do this with the fluent API of MockBuilder:

After you have build your Mock object you have to call enable() to enable the mock in the given namespace. When you are finished with that mock you should disable it by calling disable() on the mock instance.

This example illustrates mocking of the unqualified function time() in the namespace foo:

namespace foo;

use phpmock\MockBuilder;

$builder = new MockBuilder();
$builder->setNamespace(__NAMESPACE__)
        ->setName("time")
        ->setFunction(
            function () {
                return 1417011228;
            }
        );
                    
$mock = $builder->build();

// The mock is not enabled yet.
assert (time() != 1417011228);

$mock->enable();
assert (time() == 1417011228);

// The mock is disabled and PHP's built-in time() is called.
$mock->disable();
assert (time() != 1417011228);

Instead of setting the mock function with MockBuilder::setFunction() you could also use the existing FixedValueFunction:

namespace foo;

use phpmock\MockBuilder;
use phpmock\functions\FixedValueFunction;

$builder = new MockBuilder();
$builder->setNamespace(__NAMESPACE__)
        ->setName("time")
        ->setFunctionProvider(new FixedValueFunction(1417011228));

$mock = $builder->build();

It's important to note that setNamespace() should target the namespace where the function is called, not the namespace where it's being mocked. For example:

<?php

namespace App\Code;

class Subject
{
  public function foo()
  {
    time();
  }
}

In a test mocking this call:

<?php

namespace Tests\Unit;

class SubjectTest
{
  public function myTest()
  {
    $builder = new MockBuilder();
    $builder->setNamespace('\\App\\Code'); // ... etc
  }
}

Reset global state

An enabled mock changes global state. This will break subsequent tests if they run code which would call the mock unintentionally. Therefore you should always disable a mock after the test case. You will have to disable the created mock. You could do this for all mocks by calling the static method Mock::disableAll().

Mock environments

Complex mock environments of several mocked functions can be grouped in a MockEnvironment:

SleepEnvironmentBuilder

The SleepEnvironmentBuilder builds a mock environment where sleep() and usleep() return immediatly. Furthermore they increase the amount of time in the mocked date(), time() and microtime():

namespace foo;

use phpmock\environment\SleepEnvironmentBuilder;

$builder = new SleepEnvironmentBuilder();
$builder->addNamespace(__NAMESPACE__)
        ->setTimestamp(1417011228);

$environment = $builder->build();
$environment->enable();

// This won't delay the test for 10 seconds, but increase time().        
sleep(10);

assert(1417011228 + 10 == time());

If the mocked functions should be in different namespaces you can add more namespaces with SleepEnvironmentBuilder::addNamespace()

Spies

A Spy gives you access to the function invocations. Spy::getInvocations() gives you access to the arguments and return value.

As a Spy is a specialization of Mock it behaves identically. However you could ommit the third constructor parameter callable $function which would then create a spy using the existing function. E.g. a new Spy(__NAMESPACE__ , "rand") would create a spy which basically proxies PHP's built-in rand():

namespace foo;

use phpmock\spy\Spy;

function bar($min, $max) {
    return rand($min, $max) + 3;
}

$spy = new Spy(__NAMESPACE__, "rand");
$spy->enable();

$result = bar(1, 2);

assert ([1, 2]  == $spy->getInvocations()[0]->getArguments());
assert ($result == $spy->getInvocations()[0]->getReturn() + 3);

License and authors

This project is free and under the WTFPL. Responsable for this project is Markus Malkusch [email protected]. This library was inspired by Fabian Schmengler's article PHP: “Mocking” built-in functions like time() in Unit Tests.

Donations

If you like PHP-Mock and feel generous donate a few Bitcoins here: 1335STSwu9hST4vcMRppEPgENMHD2r1REK

php-mock-phpunit's People

Contributors

athos-ribeiro avatar chrisminett avatar jimlind avatar malkusch avatar marcoscoelho avatar masterodin avatar michalbundyra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

php-mock-phpunit's Issues

[QUESTION] - Deprecated Methods in phpunit 11

Hello. After upgrading to PhpUnit 11, it reports some deprecated methods used by php-mock. Is there any plan to avoid using these deprecated methods which will stop working in phpunit 12?

image

Thank you.

PHPMock::defineFunctionMock not working?

So I've read about the namespace bug and applied the recommended fix but it doesn't seem to work in this instance.
It did in another case but not here, even tried to run solo / in a different process but to no avail.
Added all the functions to the defineFunctionMock just to be safe even though most are not needed.

I've ran out of ideas, any thoughts on why this might not work?

<?php

namespace presslabs\minify;

use phpmock\phpunit\PHPMock;


class Test_PL_Minify extends \PHPUnit_Framework_TestCase {
  use PHPMock;

  public static function setUpBeforeClass() {
    # these are needed because of https://bugs.php.net/bug.php?id=68541
    # in short we use a call from an unaltered namespace then alter it which leads php confused
    PHPMock::defineFunctionMock( __NAMESPACE__, 'true_constant' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'defined' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'constant' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'pl_minify_page' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'minify_html' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'minify_css' );
    PHPMock::defineFunctionMock( __NAMESPACE__, 'minify_js' );
    # TODO refactor this duplication
  }

  function test_minify_page_minification() {
    $true_constant = $this->getFunctionMock( __NAMESPACE__, 'true_constant' );
    $true_constant->expects( $this->once() )
            ->with( 'PL_MINIFY_HTML' )
            ->willReturn( true );

    $input = 'random';

    $minify_html = $this->getFunctionMock( __NAMESPACE__, 'minify_html' );
    $minify_html->expects( $this->once() )
          ->with( $input )
          ->willReturn( 'mini' );


    $actual = pl_minify_page( $input );

    $this->assertSame( 'mini', $actual );
  }
}
namespace presslabs\minify;


function pl_minify_page( $buffer ) {
  error_log('before if' . serialize($buffer));
  if ( true_constant( 'PL_MINIFY_HTML' ) ) {
    error_log( "a" . serialize( $buffer ) );
                # gets here

    return minify_html( $buffer );
  }
  error_log('not modified');
  return $buffer;
}


function minify_css( $text ) {
  require_once( PL_PLUGINS_LIB . '/class-cssmin.php' );
  $compressor = new \CSSmin();
  $contents   = $compressor->run( $text );

  return $contents;
}


function minify_js( $text ) {
  require_once( PL_PLUGINS_LIB . '/class-JavaScriptPacker.php' );

  $packer   = new \JavaScriptPacker( $text, 'None', true, false );
  $contents = $packer->pack();

  return $contents;
}


function minify_html( $text ) {
  require_once( PL_PLUGINS_LIB . '/class-minify-html.php' );

  $buffer = \Minify_HTML::minify( $text, array(
    'cssMinifier'       => true_constant( 'PL_MINIFY_INLINE_CSS' ) ? __NAMESPACE__ . '\\minify_css' : null,
    'jsMinifier'        => true_constant( 'PL_MINIFY_INLINE_JS' ) ? __NAMESPACE__ . '\\minify_js' : null,
    'jsCleanComments'   => true_constant( 'PL_MINIFY_REMOVE_COMMENTS' ),
    'htmlCleanComments' => true_constant( 'PL_MINIFY_REMOVE_COMMENTS' )
  ) );

  return $buffer;
}


function true_constant( $name ) {
  return defined( $name ) and constant( $name ) === 'True';
}

Incompatibility with PHPUnit 8.4

In the latest release of PHPUnit, a PR was merged that refactored the Invocation interfaces, refactoring them into more specific "rules" than just one broad matcher and consequently \PHPUnit\Framework\MockObject\Matcher\Invocation was removed. A list of the stuff that is broken from this change can be found here:
https://github.com/php-mock/php-mock-phpunit/search?q=Matcher%5CInvocation&unscoped_q=Matcher%5CInvocation

Here's the upstream PR that shows these changes: sebastianbergmann/phpunit#3849

Compatibility with PHPUnit 7.4

Running zend-ldap test suite

Fatal error: Declaration of phpmock\phpunit\MockObjectProxy::__phpunit_verify() must be compatible with PHPUnit_Framework_MockObject_MockObject::__phpunit_verify(bool $unsetInvocationMocker = true) in ...

Error while mocking built-in functions like curl_init

Hi,

It is certainly a miss use of the library but I always get an error that said that the function registerMockObject does not exist.

I deeped into the library to find it and I didn't see any information in the README to fix this.

Thank you.

phpspec/prophecy is now explicitely needed for tests

Hi,

Since PHPUnit dropped phpspec/prophecy from its dependencies (sebastianbergmann/phpunit#5033), the following errors are triggered when running the testsuite with latest PHPUnit.

There were 5 errors:

1) phpmock\phpunit\MockObjectProxyTest::testExpects
PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".

/tmp/autopkgtest-lxc.hxywsvl5/downtmp/build.90r/src/tests/MockObjectProxyTest.php:40

2) phpmock\phpunit\MockObjectProxyTest::testHasMatcher
PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".

/tmp/autopkgtest-lxc.hxywsvl5/downtmp/build.90r/src/tests/MockObjectProxyTest.php:99

3) phpmock\phpunit\MockObjectProxyTest::testProxiedMethods with data set #0 ('__phpunit_getInvocationHandler', array(), PHPUnit\Framework\MockObject\InvocationHandler Object (...))
PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".

/tmp/autopkgtest-lxc.hxywsvl5/downtmp/build.90r/src/tests/MockObjectProxyTest.php:120

4) phpmock\phpunit\MockObjectProxyTest::testProxiedMethods with data set #1 ('__phpunit_setOriginalObject', array('bar'))
PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".

/tmp/autopkgtest-lxc.hxywsvl5/downtmp/build.90r/src/tests/MockObjectProxyTest.php:120

5) phpmock\phpunit\MockObjectProxyTest::testProxiedMethods with data set #2 ('__phpunit_verify', array(true))
PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".

/tmp/autopkgtest-lxc.hxywsvl5/downtmp/build.90r/src/tests/MockObjectProxyTest.php:120

Regards

David

Method was expected to be called 1 times, actually called 0 times.

The "mail" built in function is not getting mocked...Not sure what I'm missing.

Test case:

<?php

namespace Tests;
require_once __DIR__ . "/../../utilities/Util.php";

class UtilTest extends \PHPUnit\Framework\TestCase {
    use \phpmock\phpunit\PHPMock;
 
    public function testReportError()
    {

        $mail = $this->getFunctionMock(__NAMESPACE__, "mail");

        $mail->expects($this->once())
            ->willReturnCallback(
                function ($email, $subject, $body) {
                    print 'inside callback';
                    var_dump($email);
                    var_dump($subject);
                    var_dump($body);
                    $this->assertEquals("[email protected]", $email);
                    $output = ["failure"];
                    $return_var = 1;
                }
            );

        $result = \Util::reportError('testReportErrorWithNoSubjectSendEmailFails', 'testArg', 'Testing reporting errors', ['subject' => 'test']);

    }
}

SUT Util.php

 public static function reportError($mailArgs = []) {
       print("\nready to call mail");
        $result = mail($mailArgs['email'], $mailArgs['subject'], $mailArgs['body']);
        print("\nresult " . $result);

        return $result;
}

Output
composer test

phpunit --colors=always
PHPUnit 5.7.23 by Sebastian Bergmann and contributors.

F 1 / 1 (100%)
ready to call mail

result 1

Time: 59 ms, Memory: 5.00MB

There was 1 failure:

  1. Tests\UtilTest::testReportError
    Expectation failed for method name is equal to string:delegate when invoked 1 time(s).
    Method was expected to be called 1 times, actually called 0 times.

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Can't mock "exit"

When I try to mock exit I get an error:

In my test: $this->getFunctionMock('Silva', 'exit');

When I run the test:

1) Test\Unit\ApplicationTest::testRunDefaultsToHelpMenu                                            
ParseError: syntax error, unexpected 'exit' (T_EXIT), expecting identifier (T_STRING) or '('       

***\vendor\php-mock\php-mock\classes\Mock.php:180                   
***\vendor\php-mock\php-mock\classes\Mock.php:87                    
***\vendor\php-mock\php-mock-phpunit\classes\PHPMock.php:89         
***\tests\ApplicationTest.php:19                                    

ERRORS!                                                                                            
Tests: 1, Assertions: 0, Errors: 1.                                                                                                                                                              

Versions:

phpunit/phpunit                    5.4.4
php-mock/php-mock                  1.0.1 
php-mock/php-mock-integration      1.0.0 
php-mock/php-mock-phpunit          1.1.1 

Support PHPUnit 10

fyi I wanted to open a PR, but most likely to properly test it also prophecy (dev dep from this package) needs to get PHPUnit 10 support first. Looks like they're already working on it via phpspec/prophecy#585

Deprecation warnings

When invoking getFunctionMock I am getting the following deprecation warnings.

  • MockBuilder::addMethods() is deprecated and will be removed in PHPUnit 12 without replacement.
  • MockBuilder::getMockForAbstractClass() is deprecated and will be removed in PHPUnit 12 without replacement.

Mocking time function in one test method affects the other

When invoking testCorrectOtp it's the time stub defined in testNotExpiredOtp runs. Doesn't seem like correct and expected behaviour.

<?php declare(strict_types=1);
namespace AlexGeno\PhoneVerificationTests\Manager;

use PHPUnit\Framework\TestCase;


final class ManagerTest extends TestCase
{

    private \AlexGeno\PhoneVerification\Provider\Stub $providerStub;
    private \AlexGeno\PhoneVerification\Storage\Memory $storageMemory;

    const MIN_OTP_LENGTH = 2;
    const MAX_OTP_LENGTH = 6;


    const MAX_WRONG_OPT_ATTEMPTS = 3;

    use \phpmock\phpunit\PHPMock;

    protected function  setUp():void{
        $this->providerStub =  new \AlexGeno\PhoneVerification\Provider\Stub();
        $this->storageMemory =  new \AlexGeno\PhoneVerification\Storage\Memory();
    }

    public function phoneNumbers(): array
    {
        return [
            'UKR' => ['+380935258272'],
//            'US'  => ['+15417543010'],
//            'UK'  => ['+442077206312']
        ];
    }
    /**
     * @dataProvider phoneNumbers
     */
    public function testCorrectOtp($phoneNumber):void
    {
        $manager = new \AlexGeno\PhoneVerification\Manager($this->storageMemory,  $this->providerStub);
        $otp = $manager->start($phoneNumber);
        $this->assertIsInt($otp);
        $self = $manager->complete($phoneNumber, $otp);
        $this->assertEquals($self, $manager);
    }

    /**
     * @dataProvider phoneNumbers
     */
    public function testNotExpiredOtp($phoneNumber):void
    {
        $manager = new \AlexGeno\PhoneVerification\Manager($this->storageMemory,  $this->providerStub, ['otp_exp_period' => 300]);

        $time = $this->getFunctionMock('AlexGeno\PhoneVerification', "time");
        $time->expects($this->exactly(2))->willReturnOnConsecutiveCalls(0, 299);

        $otp = $manager->start($phoneNumber);
        $this->assertIsInt($otp);  //time call #1

        $self = $manager->complete($phoneNumber, $otp); //time call #2

        $this->assertEquals($self, $manager);

    }

}

Incompatible declaration of MockDisablerPHPUnit6::endTest

I was hit by this when running psalm on one of my projects (it's only part of log):

Using reflection to locate file for phpmock\phpunit\MockDisablerPHPUnit6
PHP Fatal error:  Declaration of phpmock\phpunit\MockDisablerPHPUnit6::endTest(PHPUnit\Framework\Test $test, $time) must be compatible with PHPUnit\Framework\BaseTestListener::endTest(PHPUnit\Framework\Test $test, float $time): void in php-mock/php-mock-phpunit/classes/MockDisablerPHPUnit6.php on line 44
Fatal error: Declaration of phpmock\phpunit\MockDisablerPHPUnit6::endTest(PHPUnit\Framework\Test $test, $time) must be compatible with PHPUnit\Framework\BaseTestListener::endTest(PHPUnit\Framework\Test $test, float $time): void in php-mock/php-mock-phpunit/classes/MockDisablerPHPUnit6.php on line 44

I guess, that missing : void type hint (return value) is the "incompatibility".

The void was added in 7.1.0. I see in your composer.json php>=7, so the void may be add and requirement in composer.json may be bumped to 7.1. Anyway, there is already : void in MockDisablerPHPUnit6, so its a syntax error for 7.0 I guess.

Not work if mocked in test method and tests was run from phpunit command

Example code:

class MyTest extends \PHPUnit\Framework\TestCase
{
    public function testExample(): void
    {
        $microtime = $this->getFunctionMock("My\\Namespace", 'microtime');
        $microtime->expects($this->once())
            ->willReturn('123456');
    }
}

if i try run only this test with --filter - it will pass. But if i run all tests - it will crash.
If i remove this logic to setUp method - it will pass in any case.

Add PHPUnit 8.1 compatibility

It seems that php-mock implements some interfaces which were marked as @internal in the new version of the PHPUnit and those objects aren't backward compatible anymore 😢

InvocationOrder - it is not an interface

Another bug spotted by psalm:

Using reflection to locate file for phpmock\phpunit\DefaultArgumentRemoverReturnTypes
PHP Fatal error:  phpmock\phpunit\DefaultArgumentRemoverReturnTypes cannot implement PHPUnit\Framework\MockObject\Rule\InvocationOrder - it is not an interface in php-mock/php-mock-phpunit/classes/DefaultArgumentRemoverReturnTypes.php on line 17
Fatal error: phpmock\phpunit\DefaultArgumentRemoverReturnTypes cannot implement PHPUnit\Framework\MockObject\Rule\InvocationOrder - it is not an interface in /php-mock/php-mock-phpunit/classes/DefaultArgumentRemoverReturnTypes.php on line 17

The buggy file contains:

use PHPUnit\Framework\MockObject\Matcher\Invocation as InvocationInterface;
// ....
class DefaultArgumentRemoverReturnTypes implements InvocationInterface

and there is an alias in autoload.php, that maps PHPUnit\Framework\MockObject\Matcher\Invocation to PHPUnit\Framework\MockObject\Rule\InvocationOrder, but InvocationOrder is an abstract class, thus it can't be implemented, it should rather be extended.

The interface PHPUnit\Framework\MockObject\Matcher\Invocation exists until PHPUnit 8.3.5. It disappears in 8.4.0. There is abstract class ...\Matcher\InvocationOrder since 8.4.0 and ...\Matcher\* stuff is moved to ...\Rule\* in 8.4.1.

$this->at(0) does not work

Is there any reason why this does not work?

$timeMock = $this->getFunctionMock(__NAMESPACE__, "time");

$timeMock->expects($this->at(0))
    ->willReturn(1);

$this->assertEquals(1, time());

$timeMock->expects($this->at(1))
    ->willReturn(4);

$this->assertEquals(4, time());

Declaration of Codeception\Test\Test::toString() must be compatible with PHPUnit\Framework\SelfDescribing::toString():

I have been using PHP-mock-phpunit to mock out some built in PHP functions, and compared to some other PHP mocking libraries I have tried, it seems to work pretty well. And it also seems to integrate OK with CodeCeption's take on PHPUnit tests so that was good.

However, now that my unit tests are running and I switch back to continue on my phpbrowser acceptance tests with CodeCeption, I get the following error:

Codeception PHP Testing Framework v3.1.2
Powered by PHPUnit 8.5.2 by Sebastian Bergmann and contributors.
Running with seed: 

PHP Fatal error:  Declaration of Codeception\Test\Test::toString() must be compatible with PHPUnit\Framework\SelfDescribing::toString(): string in /project/vendor/codeception/codeception/src/Codeception/Test/Test.php on line 18

Fatal error: Declaration of Codeception\Test\Test::toString() must be compatible with PHPUnit\Framework\SelfDescribing::toString(): string in /projectvendor/codeception/codeception/src/Codeception/Test/Test.php on line 18

and that's where it stops. I can't get the acceptance test to run at all.

If I use composer to uninstall PHP-mock-phpunit, then the acceptance tests fire up fine.

Presumably PHPMock is tweaking some classes behind the scenes and that is breaking things...

Here is my composer.json:

{
    "name": "my project",
    "description": "stuff",
    "require-dev": {
        "phpunit/phpunit": "^8",
        "codeception/codeception": "^3",
        "guzzlehttp/guzzle": "^6.3",
        "captbaritone/mailcatcher-codeception-module": "1.*",
        "codeception/specify": "^1",
        "codeception/stub": "^3",
        "dms/phpunit-arraysubset-asserts": "^0.1.0",
        "php-mock/php-mock-phpunit": "^2.6"
    },
    "require": {
        "mailjet/mailjet-apiv3-php": "^1.4",
        "stripe/stripe-php": "^7.14"
    }
}

Any suggestions?

Error: Call to undefined method phpmock\phpunit\MockObjectProxyNoReturnTypes::will()

I am trying to create a mock of rand() that will be called three times, but return a duplicate:

    $rand = $this->getFunctionMock("CashID", "rand");
    $rand->will($this->onConsecutiveCalls($exp_nonce1, $exp_nonce1, $exp_nonce2));

However, I receive an error that will() is undefined. I successfully use a similar mock statement elsewhere on a standard PHPUnit mock.

Declaration of phpmock\phpunit\MockDisablerPHPUnit6::endTest(PHPUnit\Framework\Test $test, $time) must be compatible with PHPUnit\Framework\BaseTestListener::endTest(PHPUnit\Framework\Test $test, float $time): void in /home/vagrant/Code/boursify-app/vendor/php-mock/php-mock-phpunit/classes/MockDisablerPHPUnit6.php on line 50

When I run PHPUnit, I get the following error:

Declaration of phpmock\phpunit\MockDisablerPHPUnit6::endTest(PHPUnit\Framework\Test $test, $time) must be compatible with PHPUnit\Framework\BaseTestListener::endTest(PHPUnit\Framework\Test $test, float $time): void in /home/vagrant/Code/boursify-app/vendor/php-mock/php-mock-phpunit/classes/MockDisablerPHPUnit6.php on line 50

Ubuntu 18.04.1
composer version: 1.10.6 2020-05-06 10:28:10
PHP version: 7.3.13
phpunit: 8.5.3
php-mock-phpunit: 2.6.0

MockDisablerPHPUnit6::endTest does not seem to adhere to the BaseTestListener::endTest interface.

What could fix this issue?

Thank you :)

Exception Message is unclear

First of all I just want to say I really like the library, thank you so much for creating it :)

I do think this Exception Message should be improved.

When I create a mocked function like so:

$passthru = $this->getFunctionMock('My\Project', 'passthru');
$passthru->expects($this->exactly(2))->withConsecutive(['arg1'], ['arg2']);

The error message that I get when the test fails (because the code being tested doesn't actually call passthru() yet) is like this:

1) Tests\MyProjectTest::myTestMethod 
Expectation failed for method name is equal to <string:delegate> when invoked 2 time(s).       
Method was expected to be called 2 times, actually called 0 times.                                                                                                                        

Instead of <string:delegate> it would be helpful if it said passthru, or even better, something like: Expectation failed for passthru to be invoked 2 time(s)

I know the matchers and exceptions come from PHPUnit, but is there a way to send in better messages?

phpunit 8.3: cannot implement PHPUnit\Framework\MockObject\Rule\InvocationOrder

Using PHPUnit 8.3.5, I've no such thing as \PHPUnit\Framework\MockObject\Matcher\Invocation::class.

As such, the following code in autoload.php

if (class_exists(\PHPUnit\Framework\MockObject\Rule\InvocationOrder::class)) {
    class_alias(
        \PHPUnit\Framework\MockObject\Rule\InvocationOrder::class,
        \PHPUnit\Framework\MockObject\Matcher\Invocation::class
    );

causes

PHP Fatal error:  phpmock\phpunit\DefaultArgumentRemoverReturnTypes cannot implement PHPUnit\Framework\MockObject\Rule\InvocationOrder - it is not an interface in /vendor/php-mock/php-mock-phpunit/classes/DefaultArgumentRemoverReturnTypes.php on line 17

PHPUnit 8.4 seems to work though

Multiple returns

Hi,
I'm trying to create a mock of file_get_contents function. On the first call, it should throw an exception, but on the second call it should return a value. How can I mock it?:

try {
    $content = 'data:image/jpeg;base64,'.base64_encode(file_get_contents($url));
} catch (\Exception $e) {
    $content = 'data:image/jpeg;base64,'.base64_encode(file_get_contents(realpath(__DIR__.'/path/to/my/image.png')));
}

Error: addMatcher() must implement interface PHPUnit\Framework\MockObject\Matcher\Invocation

I tried to get this to work with PHPUnit 6.4 (since 6.5 is having issues) and kept getting these errors:

There were 2 errors:

  1. foo\BuiltinTest::testTime
    TypeError: Argument 1 passed to PHPUnit\Framework\MockObject\InvocationMocker::addMatcher() must implement interface PHPUnit\Framework\MockObject\Matcher\Invocation, instance of phpmock\phpunit\DefaultArgumentRemover given, called in /data/wordpress/wp-content/plugins/zip-recipes/vendor/php-mock/php-mock-phpunit/classes/PHPMock.php on line 79

/data/wordpress/wp-content/plugins/zip-recipes/vendor/php-mock/php-mock-phpunit/classes/PHPMock.php:79
/data/wordpress/wp-content/plugins/zip-recipes/plugins/RecipeIndex/tests/SampleTest.php:15

phpmock\phpunit\PHPMock not installing

Hi,
Successfully installed php-mock/php-mock and php-mock/php-mock-integration but unable to install php-mock/php-mock-phpunit.

This is the output:

Using version ^1.1 for php-mock/php-mock-phpunit
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- php-mock/php-mock-phpunit 1.1.2 requires php-mock/php-mock-integration ^1 -> satisfiable by php-mock/php-mock-integration[1.0.0] but these conflict with your requirements or minimum-stability.
- php-mock/php-mock-phpunit 1.1.1 requires php-mock/php-mock-integration ^1 -> satisfiable by php-mock/php-mock-integration[1.0.0] but these conflict with your requirements or minimum-stability.
- php-mock/php-mock-phpunit 1.1.0 requires php-mock/php-mock-integration ^1 -> satisfiable by php-mock/php-mock-integration[1.0.0] but these conflict with your requirements or minimum-stability.
- Installation request for php-mock/php-mock-phpunit ^1.1 -> satisfiable by php-mock/php-mock-phpunit[1.1.0, 1.1.1, 1.1.2].

Installation failed, reverting ./composer.json to its original content.

Not working with PHPUnit 6.5

Hi, the library is not working with PHPUnit 6.5 (phpunit-mock-objects 5).

<?php declare(strict_types=1);

namespace My;

use phpmock\phpunit\PHPMock;

class WillItWorkTest extends \PHPUnit\Framework\TestCase
{
    use PHPMock;

    public function testFoo(): void
    {
        $time = $this->getFunctionMock(__NAMESPACE__, 'time');
    }
}

Results in:

PHP Fatal error: Interface 'PHPUnit_Framework_MockObject_Matcher_Invocation' not found in /.../vendor/php-mock/php-mock-phpunit/classes/DefaultArgumentRemover.php on line 15

Version of relevant installed packages:
phpunit/phpunit 6.5.1
phpunit/phpunit-mock-objects 5.0.3
php-mock/php-mock 2.0.0
php-mock/php-mock-integration 2.0.0
php-mock/php-mock-phpunit 2.0.0

May be related to sebastianbergmann/phpunit-mock-objects#388 ?

Increase phpunit versions

Is there a reason this is locked to phpunit 4.0.0 || 5.0.0, and not something like 5.* ? If there's something breaking in one of the later versions, I'd be happy to help fix it. I want to use this tool with more recent phpunit versions.

sample test doesn't work

here is test:

<?php
class UtilTest extends \PHPUnit\Framework\TestCase {
    use \phpmock\phpunit\PHPMock;
    public function testTime()
    {
        $time = $this->getFunctionMock(__NAMESPACE__, "time");
        $time->expects($this->once())->willReturn(3);
        $this->assertEquals(3, time());
    }
}

and console output:

$ vendor/bin/phpunit 
PHPUnit 5.7.23 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 48 ms, Memory: 5.25MB

There was 1 failure:

1) UtilTest::testTime
Failed asserting that 1508265379 matches expected 3.

/Users/barton/projects/wisnet/wisnetds/Tests/utilities/UtilTest.php:13

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

And php version:

~/projects/wisnet/wisnetds (unittest)$ php -v
PHP 5.6.31 (cli) (built: Aug  7 2017 20:28:16) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
~/projects/wisnet/wisnetds (unittest)$ 

Data are leaking between tests

This may be my obvious error, but since there's no real documentation I cannot verify it.
While testing rather complicated (and to be honest poorly written ;)) I came across one problem - all tests are green if run one by one, but they generate weird errors while all tests are run at once. I even tried using runInSeparateProcess annotation for all tests but it get even worse ;)

Example: https://github.com/kiler129/TorrentGhost/blob/fetchJobTests/tests/Http/FetchJobTest.php
Travis: https://travis-ci.org/kiler129/TorrentGhost/builds/89312464
screenshot 2015-11-04 22 10 35

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.