Giter Club home page Giter Club logo

phpunit-mock-objects's Introduction

Latest Stable Version Minimum PHP Version Build Status

phpunit-mock-objects

phpunit-mock-objects is the default mock object library for PHPUnit.

phpunit-mock-objects's People

Contributors

deepdiver1975 avatar dlondero avatar edorian avatar fabian avatar firehed avatar giorgiosironi avatar grahamcampbell avatar jeroendedauw avatar josemalonsom avatar ksimka avatar kubawerlos avatar lapistano avatar lcobucci avatar lstrojny avatar makasim avatar marioblazek avatar mattrx avatar nicolas-grekas avatar prolic avatar remicollet avatar roman-shuhov avatar ruudk avatar sawmurai avatar sebastianbergmann avatar stefk avatar thomasweinert avatar trowski avatar tzi avatar vinai avatar whatthejeff 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpunit-mock-objects's Issues

Error when trying to mock isset() or echo() methods

The following code produces a PHP Parse error in PHPUnit 3.4:

$this->getMock('SomeClass', array('echo', 'isset'));

As far as I can see, the same error should occur in PHPUnit 3.5 (I don't have a working 3.5 environment at hand). The blacklistedMethodNames array in PHPUnit_Framework_MockObject_Generator does not contain the above methods, so when generating the mock the resulting PHP code is invalid.

I'm not sure whether there are other methods missing from the blacklist, these two are the ones I just encountered.

Errors Mocking the Zend Framework Zend_XmlRpc_Client_ServerProxy class

With PHPUnit_MockObject-1.0.5 (PHPUnit 3.5.17) I run into the following style of errors when mocking Zend_XmlRpc_Client_ServerProxy objects:

MyClassTest::test_doSomething_Calls_ZendXmlRpcClientServerProxy_remoteMethod_Once
Expectation failed for method name is equal to <string:remoteMethod> when invoked 1 time(s)
Parameter count for invocation Zend_XmlRpc_Client_ServerProxy::remoteMethod(<integer:100>, <double:0>, <double:100>) is too low.

The error is not reported under PHPUnit_MockObject-1.0.0.

Notice when mocking a PHP extension class and calling expects()

<?php
class Test extends PHPUnit_Framework_TestCase
{
    public function test()
    {
        $oauth = $this->getMockBuilder('OAuth')
                      ->disableOriginalConstructor()
                      ->setConstructorArgs(array('key', 'secret'))
                      ->disableOriginalClone()
                      ->setMethods(array('fetch', 'lastResponse'))
                      ->getMock();

        $oauth->expects($this->any())
              ->method('fetch')
              ->will($this->returnValue(true));
    }
}

The $oauth->expects() call will trigger this notice:

Undefined property: Mock_OAuth_c48856b9::$invocationMocker

Cannot create mock object for abstract class

Using newly install PHPUnit 3.5

Trying to create mock iwth getMockForAbstractClass(), following error is emitted:
Class 'PHPUnit_Framework_MockObject_Generator' not found

I am using PHPUnit/Autoload - and it does a great job loading other classes, so wondering why it is not finding Generator, I looked into PHPUnit code.

In PHPUnit/Framework/Testcase line 1123:
PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass()

method invocation is found, while looking in PHPUnit/Framework/MockObject folder, I noticed that there's only one class MockBuilder, and no Generator. Not sure if Generator is defined somewhere else, but this can be probable source of the issue.

Enable stack traces in failure messages

Since the method expectations are verified after the test method completes, the entire stack trace is stripped (and would be useless if shown). When assertions fail, the exception is thrown on the line where the assertion occurs. I'd really like that behavior with method expectations.

If the invocation matchers were to create an exception when they are defined, they would capture this information. When verify() fails, the exception could be thrown instead of creating a new one.

The other option is to capture the file/line using debug_backtrace() and throw a SyntheticError instead, but that wouldn't be as complete.

Mocking class Imagick of pecl/imagick 3.0.0 fails with PHPUnit 3.4.2 and 3.5 beta1

When mocking class Imagick of the pecl/imagick extension 3.0.0, mocking fails with the following error message:

Fatal error: Call to a member function verify() on a non-object in /usr/share/php/PHPUnit/Framework/MockObject/Generator.php(172) : eval()'d code on line 4358

The testcase is quite easy:

class test extends PHPUnit_Framework_TestCase
{
    public function test()
    {
        $mock = $this->getMock('Imagick');
    }
}

The server is running Ubunt 10.04 with PHP 5.3.2 from the Ubuntu repository, Imagick installed via pecl and PHPUnit installed from PEAR.

Parse error: syntax error, unexpected T_LNUMBER, expecting T_STRING in C:\php\PEAR\PHPUnit\Framework\MockObject\Generator.php(184) : eval()'d code on line 11

Parse error: syntax error, unexpected T_LNUMBER, expecting T_STRING in C:\php\PEAR\PHPUnit\Framework\MockObject\Generator.php(184) : eval()'d code on line 11

With PHPUnit 3.5 / PHPUnit MockObject 1.0.9; I see fatal errors with the below test case:

<?php
require_once 'PHPUnit/Framework.php';

class MockObjectBugTest extends PHPUnit_Framework_TestCase {
    public function test() {
        $matcher = $this->getMock('ExampleMatcher', array('0'));

        $matcher->expects($this->once())
                    ->method('match');
    }
}

// A simple mock class
class ExampleMatcher {
    public function __construct($rp_id) {
        $this->rp_id = $rp_id;
    }
    public function match(CLS_address $address, CLS_address_rp $rp) {
        $rp->setRPID($this->rp_id);

        return $rp;
    }
}

Of course; this is just me being half asleep and passing in an invalid method name to the mock framework (I thought I was passing in arguments; doh).

Unfortunately it results in a fatal error on code I can't see unless I get into the depths of the framework. An exception would be handy.

From http://www.php.net/manual/en/functions.user-defined.php

Function names follow the same rules as other labels in PHP. A valid function name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.

Mocking class Imagick

I have a quite similar error related to issue #29.

$this->mockedImage = $this->getMock(
        'Imagick',
        array(),
        array($this->filePath),
        '',
        false,
        false
    );

    $this->mockedImage
         ->expects($this->once())
         ->method('solarizeImage')
         ->with($this->threshold)
         ->will($this->returnValue(true));

This produce the following error:

PHP Fatal error: Call to a member function expects() on a non-object in /usr/share/php/PHPUnit/Framework/MockObject/Generator.php(170) : eval()'d code on line 7317

I use Imagick 3.0.1, ImageMagick 6.6.9-4 and phpunit 3.5.13

Is null a legal value for $methods when creating mocks?

Hey

I'm confused as to whether "null" is a legal value for $methods when creating mock objects. My understanding is that null means "don't replace any methods with test doubles," whereas empty array() means "replace all methods with test doubles." We have some code here at Etsy that breaks without the null behavior.

MockBuilder.php seems to indicate that null is NOT an allowed value, because it's using an array type hint in the argument signature:

https://github.com/sebastianbergmann/phpunit-mock-objects/blob/1.0/PHPUnit/Framework/MockObject/MockBuilder.php#L150

However, Generator.php seems to be expecting null as a possible value for $methods:

https://github.com/sebastianbergmann/phpunit-mock-objects/blob/1.0/PHPUnit/Framework/MockObject/Generator.php#L162

Is the array typehint an oversight, or is the use of null being phased out? Thanks!

AbstractMocking does not work as expected

It would appear, from my test case at last that getMockForAbstractClass() is not working.

If I have the following which fails

abstract class Foo
{
    public function t()
    {
        return 2;
    }
}


public function testT()
    {
        // Create a stub for the abstract class.
        $stub = $this->getMockForAbstractClass('Foo');

        // Configure the stub.
        $stub->expects($this->any())
             ->method('t')
             ->will($this->returnValue(4));

        $this->assertEquals(4, $stub->t());
    }

If I change the Foo class to concrete and the stub to $this->getMock('Foo') then it works as expected.

Am I doing something wrong or is this a bug?

I'm using PHPUnit 3.6.4

"expects any" together with "with equalsto" fails for test cases where that method does not get called

Sample test case:

<?php
class MyService {
    public function hello($name) {
        return "hello $name";
    }
}

class MyController {
    private $service;

    public function __construct($service) {
        $this->service = $service;
    }

    public function doSomethingWithService() {
        return $this->service->hello('me');
    }

    public function doSomethingWithoutService() {
        return 'error';
    }
}

class MyTest extends PHPUnit_Framework_TestCase {
    private function createServiceMock() {
        $myMock = $this->getMockBuilder('MyService')->disableOriginalConstructor()->getMock();
        $myMock->expects($this->any())->method('hello')->with($this->equalTo('me'))->will($this->returnValue('goodbye you'));
        return $myMock;
    }

    public function testUsingMock() {
        $controller = new MyController($this->createServiceMock());
        $this->assertEquals('goodbye you', $controller->doSomethingWithService());
    }

    public function testWithoutMock() {
        $controller = new MyController($this->createServiceMock());
        $this->assertEquals('error', $controller->doSomethingWithoutService());
    }
}

Command line output:

> phpunit testcase.php 
PHPUnit 3.5.5 by Sebastian Bergmann.

.F

Time: 0 seconds, Memory: 4.00Mb

There was 1 failure:

1) MyTest::testWithoutMock
Expectation failed for method name is equal to <string:hello> when invoked zero or more times.
Mocked method does not exist.


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

Expected behavior:

The test that should that doesn't call the method which has expects($this->any()) but does not call the mocked method should pass without complaints.

Incomplete docblocks

Many of the docblocks in this extension are incomplete, with just @param and @return set but with no description. This makes using autocomplete very difficult. I make a PR for this but I really cant be sure what the methods do so it's better I dont try. Would it be possible to add short descriptions to the beginning of the docblocks?

Mock expectations shouldn't be allowed on not existent methods

In PHPUnit 3.4.15, this test case:

getMock('DummyInterfaceWithoutMethods');
                $mock->expects($this->any())
                        ->method('doesNotExist')
                        ->will($this->returnValue('foo'));
        }
}
interface DummyInterfaceWithoutMethods {}

does not fail. If an error were raise, it will be simple to find mystakes and typos in method names.

Mocking undeclared methods impossible since 1.0.4

Example

<?php
class Foo
{
}

class Test extends PHPUnit_Framework_TestCase
{
    public function testStubbingUndeclaredMethodsWorks()
    {
        $stub = $this->getMock('Foo', array('bar'));

        $stub->expects($this->any())
             ->method('bar')
             ->with($this->equalTo('baz'))
             ->will($this->returnValue('foobarbaz'));

        $this->assertEquals('foobarbaz', $stub->bar('baz'));
    }
}

Actual Output

sb@vmware ~ % phpunit Test
PHPUnit @package_version@ by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 4.25Mb

There was 1 failure:

1) Test::testStubbingUndeclaredMethodsWorks
Expectation failed for method name is equal to <string:bar> when invoked zero or more times
Parameter count for invocation Foo::bar() is too low.

/usr/local/src/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher.php:180
/usr/local/src/phpunit-mock-objects/PHPUnit/Framework/MockObject/InvocationMocker.php:138
/home/sb/Test.php:17

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

Expected Output

sb@vmware ~ % phpunit Test
PHPUnit @package_version@ by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 4.25Mb

OK (1 test, 2 assertions)

Passing certain uncloneable objects to a mocked method triggers a fatal error.

The PHPUnit_Framework_MockObject_Invocation class triggers a fatal error when certain uncloneable objects are passed to mocked methods. For instance:

<?php

class Sample
{
    public function doSomething($arg) {}
}

class SampleTest extends PHPUnit_Framework_TestCase
{
    public function testDoSomething()
    {
        $sample = $this->getMock('Sample');
        $sample->doSomething(new AppendIterator());
    }
}

?>

This happens due to a shortcoming in the way that objects are cloned by PHPUnit_Framework_MockObject_Invocation::cloneObject(). The method attempts to filter out the objects which are not cloneable, but some uncloneable objects pass.

I suspect that this could be solved with ReflectionClass::isCloneable() which is in the PHP trunk, but has yet to make it into a stable PHP release just yet. By inspecting the method here: http://svn.php.net/repository/php/php-src/trunk/ext/reflection/php_reflection.c, you can see that if clone_obj is null, the object is not cloneable. Unfortunately, I'm unaware of any way to test for this in PHP.

The best approach I could come up with was to write a patch that checks for known extensions/classes from the PHP core that are not cloneable using the knowledge gained from ReflectionClass::isCloneable(). The patch can be found here: http://gist.github.com/513739.

This doesn't help too much with 3rd-party extensions, but it's at least a better solution until ReflectionClass::isCloneable() is available.

Mock caching

Framework\MockObject\Generator::getMock() caches the created objects by original class name and methods when no mock class name is specified.

When the same object/method combination is later stubbed again with different return values (again without providing a mock class name), always the first defined value is returned.

Since this behavior could lead to unforeseen errors, I would like to recommend one of these options:

  1. Issue an error when the stubbing of an existing mock object is altered.
  2. Actually alter the stubbing by applying the new options.

Same mock in multiple tests

I have a problem with mock which shall be used in multiple tests. In second test it returns NULL instead of value from callback.

isPublic(); } } class MockTest extends PHPUnit_Framework_TestCase { private $public = FALSE; public function isPublic() { return $this->public; } public function testIsRecordable() { $mockProgram = $this->getMockBuilder('Program') ->setMockClassName("ProgramMock") ->setMethods(array('isPublic')) ->disableOriginalConstructor() ->getMock(); $mockProgram ->expects($this->any()) ->method('isPublic') ->will($this->returnCallback(array($this, "isPublic"))); ``` $actual = $mockProgram->isRecordable(); $this->assertFalse($actual); $this->public = TRUE; $actual = $mockProgram->isRecordable(); $this->assertTrue($actual); return $mockProgram; ``` } /** - @Depends testIsRecordable **/ public function testSetRecord($mockProgram) { $actual = $mockProgram->isRecordable(); $this->assertTrue($actual); $this->public = FALSE; $actual = $mockProgram->isRecordable(); $this->assertFalse($actual); } }

Mocking methods with variable parameter count impossible since 1.0.4

Assume an interface definition of
public function create($objectName);
that is documented and implemented as taking 1+n arguments
public function create($objectName) {
return call_user_func_array(array($this->objectContainer, 'create'), func_get_args());
}

Until 1.0.3 the interface could be mocked and with() assertions worked with any number of parameters, as expected. With 1.0.4 the use of func_get_args() has been removed, this this is no longer possible.

I take this is intended behaviour, so is there a suggested workaround?

PHPUnit_Runner_IncludePathTestCollector::collectTests() ignores new filter iterator

If the collector has a filter iterator, it constructs a new one with the same class and pases in the new file iterator. However, it stores the new filter iterator in a local variable instead of the instance field of the same name:

if ($this->filterIterator !== NULL) {
    $class          = new ReflectionClass($this->filterIterator);
    $filterIterator = $class->newInstance($iterator);
}

$filterIterator should probably be $this->filterIterator.

Cloning paramaters in mocked methods/objects

I've hit against an issue where I am expecting a paramater to be passed by reference in a mocked object and it isn't working. It seems that it is being cloned.

I created a Stack Overflow post on this as I wasn't sure if I was being silly.

http://stackoverflow.com/questions/5170747/pass-by-reference-in-a-callback-when-mocking-in-phpunit

Comment on the accepted answer suggested that feedback was needed on this cloning idea.

I would say that it is a bad idea based on this use case as its not expected. I'm not sure of the arguments for it so I can't really argue very hard.

mocked_class.tpl.dist inconsistencies?

  1. PHPUnit_Framework_MockObject_InvocationMocker has no constructor, but __phpunit_getInvocationMocker() passes $this when instantiating it. While it will merely be ignored AFAIK, it should probably be removed.
  2. Should __phpunit_cleanup() set the static invocation mocker to NULL?

I apologize for not creating a test for #2, but I'm heading out and didn't want to forget about it over the weekend.

Cannot mock methods that return a reference

Moved here from sebastianbergmann/phpunit#141.

I am trying to mock Facebook's REST client for our user class and am having trouble mocking calls to fql_query() which returns a reference.

public function &fql_query($query) { ... }

I created a simple test case to verify the issue.

class ClassUnderTest
{
    public $value = 'result';

    public function &method() {
        return $this->value;
    }
}

class ReferenceTest extends PHPUnit_Framework_TestCase
{
    public function testNormalCall() {
        $t = new ClassUnderTest();
        $this->assertEquals('result', $t->method());
    }

    public function testMockCall() {
        $t = $this->getMock('ClassUnderTest', array('method'));
        $t->expects($this->once())->method('method')->will($this->returnValue('result'));
        $this->assertEquals('result', $t->method());
    }
}

The second test fails because PHP raises an E_NOTICE

Only variable references should be returned by reference

in the generated mock.

Make a test fail if a mocked method is not expected to be invoked (Reopen)

Hi, i found this issue in the closed section : #9

I reopened it because i consider it pretty major.

Here is an example, i want to test this :

class UniverseController
{
   public function doMaintenance(Universe $universe)
   {
      if (!$universe->peopleIsHappy())
      {
         $universe->giveJoy();
      }
   }
}
//Universe object
class Universe
{
   public function peopleIsHappy()
   {
      return true;
   }

   public function giveJoy()
   {
      //Give Joy
   }

   public function killEveryone()
   {
      die ("Everyone's dead now.");
   }
}

Now here's the test for the doMaintenance Method.

class UniverseControllerTest extends PHPUnit_Framework_TestCase
{
   public function testDoMaintenance()
   {
      $universeMock = $this->getMock("Universe");

      $universeMock->expects($this->once())->method("peopleIsHappy")->will($this->returnValue(false));
      $universeMock->expects($this->once())->method("giveJoy");

      $subject = new UniverseController();

      $subject->doMaintenance($universeMock);
   }
}

So if you run it as is, now, everything is fine.

Now imagine there's a troll that edits the UniverseController code and accidentally calls the killEveryone method as in this :

class UniverseController
{
   public function doMaintenance(Universe $universe)
   {
      if (!$universe->peopleIsHappy())
      {
         $universe->giveJoy();
      }
      $universe->killEveryone();
   }
}

You can confirm that it's a terrible error. Now rerun the test, still passes. Even though the $universe is a mock, it's really dangerous to ignore "unexpected" invocations.

The same thing happen if you take the other way around, if initially the doMaintenance() method behavior WAS to killEveryone() and you forget to expect it, the test will run, and someone come and see this line makes no sense, remove it and tests still good. So basically you can change the "contract" of a method without breaking tests.

So to me it is clear the test SHOULD fail, and i don't really understand the argument emitted in the issue i linked above. If it breaks a lot of test to fail unexpected mocked methods calls, then i'd say the test aren't really viable, they're assuming a mocked method call to return null when not expected at all.

If it would be too big to change this, maybe there could be a sort of "strict" mock that would NOT allow unexpected methods to be called.

I checked the code of the PHPUnit_Framework_MockObject_InvocationMocker::invoke method and it clearly isn't trivial to make sure the $invocation->methodName has at least once matcher attached to it, but my example above shows a clear flaw in the mocking system.

What do you think?

Ensure an exact amount of arguments are passed to a mocked function.

Is there a way to ensure that an exact amount of parameters are passed to a mocked function? For example, expect 3 parameters and fail if 4 are passed.
I expected to be able to achieve this with the with() function but it only fails when less than the expected amount are passed.

Class Posing support for Mock Objects

A mock object can be used anywhere in the program where the program expects an object of the mocked class. However, this only works as long as the object can be passed into the context where the original object is used.

Consider the following example:

<?php
class SomeClass
{
    public function doSomething()
    {
        $object = new SomeOtherClass;
        // ...
    }
}
?>

With the code above, it is impossible to run a unit test for the SomeClass::doSomething() method without also creating an object of SomeOtherClass. As the method creates the object of SomeOtherClass itself, we cannot inject a mock object in its stead.

In a perfect world, code such as the above could be refactored using Dependency Injection:

<?php
class SomeClass
{
    protected $object;

    public function __construct(SomeOtherClass $object)
    {
        $this->object = $object;
    }

    public function doSomething()
    {
        // ...
    }
}
?>

Unfortunately, this is not always possible (not because of technical reasons, though).

This is where the set_new_overload() function of the test-helpers extension to the PHP interpreter comes into play. It can be used to register a callback that is automatically invoked when the new operator is executed:

<?php
class Foo {}
class Bar {}

function callback($className) {
    if ($className == 'Foo') {
        $className = 'Bar';
    }

    return $className;
}

var_dump(get_class(new Foo));

set_new_overload('callback');
var_dump(get_class(new Foo));
?>

string(3) "Foo"
string(3) "Bar"

This issue is about wrapping set_new_overload() in the PHPUnit Mock Object API.

expectation on mock fails when object under test changes

This may be a clone of some other bug, because I've found some similar, but I can't be sure, so here it is. The test cases are identical, the only difference is than in the latter test the object under test changes a protected property, which causes an expectation to fail, most likely due to object cloning.

class Caller_works {
    function callNotify($ob) {
        $ob->notify($this);
    }
}

class Caller_fails {
    protected $notified;
    function callNotify($ob) {
        $ob->notify($this);
        $this->notified = $ob;
    }
}

class ContainerTest extends PHPUnit_Framework_TestCase {
    function testCallerWorks() {
        $caller = new Caller_works();
        $callee = $this->getMock('StdClass', array('notify'));
        $callee->expects($this->once())->method('notify')->with($caller);
        $caller->callNotify($callee);
    }

    function testCallerFails() {
        $caller = new Caller_fails();
        $callee = $this->getMock('StdClass', array('notify'));
        $callee->expects($this->once())->method('notify')->with($caller);
        $caller->callNotify($callee);
    }
}

MockObject_Generator::getMock replaces all methods instead of none

Calling PHPUnit_Framework_MockObject_Generator::getMock('MyClass') replaces all the methods of MyClass rather than none.
(This method is called from PHPUnit_TestCase::getMock.)

Ultimately, in PHPUnit_Framework_MockObject_Generator::generateMock, empty array has a different meaning than null.

Calls to mocked methods with referenced parameters fail after assignment

When mocking a method that takes a parameter by reference, method arguments are susceptible to later assignment.

The following test case passes in PHPUnit 3.4.13 but fails in PHPUnit 3.5.13 + PHPUnit_MockObject 1.0.8:

<?php

class Mock_Reference_Test_Class
{
    // Parameter is passed by reference
    public function method( & $var ) {}
}

class Mock_Reference_Test extends PHPUnit_Framework_TestCase
{
    public function test()
    {
        $arg = 'a';

        $mock = $this->getMock('Mock_Reference_Test_Class', array('method'));
        $mock->expects($this->any())
            ->method('method')
            ->with($this->identicalTo($arg));

        $mock->method($arg);

        // This assignment causes the test to fail
        $arg = 'b';
    }
}
PHPUnit 3.5.13 by Sebastian Bergmann.

There was 1 failure:

1) Mock_Reference_Test::test
Expectation failed for method name is equal to <string:method> when invoked zero or more times.
Parameter 0 for invocation Mock_Reference_Test_Class::method(<string:b>) does not match expected value.
Failed asserting that <string:b> is identical to <string:a>.

Mocking vs copying

PHPUnit appears to be inadvertedly copying whilst mocking; in some cases.

<?php
class ATest extends PHPUnit_Framework_TestCase {

    public function testCat() {
    $x = $this->getMock('foo');

    $a = new stdClass();

    $x->expects($this->once())
        ->method('b')
        ->with($a);

    $x->b($a);

    $a->y = 3;
        }
    }

    class foo {
        function b($x) {
    }
  }

Expected:
Test passes

Actual:
---------- PHPUnit ----------
PHPUnit 3.5.0 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 3.25Mb

There was 1 failure:

1) ATest::testCat
Expectation failed for method name is equal to <string:b> when invoked 1 time(s).
Parameter 0 for invocation foo::b(stdClass(...)) does not match expected value.
Failed asserting that 
stdClass Object
(
)
 is equal to 
stdClass Object
(
    [y] => 3
)
.


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

Output completed (1 sec consumed)

Annoyingly; this appears to be some kind of copy-on-write problem - the object passed in gets cast to an array or something, perhaps in function_get_args

identicalTo() matcher for mock objects parameters

Since matcher's object parameters are cloned, identicalTo() in with() calls on mock expectations always fails.
I thought it can save the spl_object_hash() somewhere before cloning the object, so that it can be matched even if the original object is thrown away. If you're interested, I can implement it.

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.