2
votes

I can't get Mockery to create a simple dummy:

<?php
require_once '../vendor/autoload.php'; // composer autoload mockery

class Foo {
    private $required;
    public function __construct($required){
        $this->required = $required;
    }
    public function bar(){
        // do stuff with $this->required
    }
}

class FooTest extends PHPUnit_Framework_TestCase  {
    public function testBar(){
        $mock = \Mockery::mock('\Foo');
        $mock->bar();
    }
}

Running that PHPUnit test gives the error:

BadMethodCallException: Method Mockery_0_Foo::bar() does not exist on this mock object

What am I doing wrong?

2

2 Answers

3
votes

If you'd like to do php unit testing on "Foo" class and mocks "Required" object. Just do it like below:

class Foo {
    private $required;
    public function __construct(\Required $required){
        $this->required = $required;
    }
    public function bar(){
        return $this->required->getTextFromBarTable();
    }
}

class FooTest extends PHPUnit_Framework_TestCase  {
    public function testBar(){
        $mock = \Mockery::mock('\Required'); // Dummy, There are no properties or methods.

        /**
        * Stub "getTextFromBarTable" method of \Required class 
        * and fakes response by returning "return this text".
        */
        $mock->shouldReceive('getTextFromBarTable') 
             ->andReturn('return this text');

        // create "Foo" Object by using $mock instead of actual "\Required" Object.
        $foo = new Foo($mock); 
        $response = $foo->bar();

        $this->assertEqual('return this text', $response);
    }
}

You must NOT stub or mock class that you want to do unit testing on. Just do it on Dependency Class like "\Required".


we do STUB or MOCK to separate EXTERNAL logic that could affect INTERNAL logic of method we're going to test. In this case I assumed \Required class has "getTextFromBarTable" method and this method will connect and get 'text' field from database. The "testBar" method will be broken if our database doesn't have text field. To get rid of external problems I did stub on "\Required" and every times I use "getTextFromBarTable" method. It will always return me "return this text".

1
votes

I had to explicitly state what methods the mock makes stubs of:

class FooTest extends PHPUnit_Framework_TestCase  {
    public function testBar(){
        $mock = \Mockery::mock('Foo');
        $mock->shouldReceive('bar');
        $mock->bar();
    }
}

I'm curious if there's a way round this, something which either:

  1. implicitly catches all method calls that are defined in Foo, or
  2. implicitly catches all method calls, whether or not they are defined in Foo