Pregunta

I’m having some weird errors with some tests I’m trying to make, and I would like to ask for your help in figuring out.

I’ve been asked to use Mockery for mocking, which I had never used before.

Here I will publish heavily modified versions of the files in question (to remove corporate references), and you can check the output error I get at the end.

Composer:

{
    "autoload": {
        "psr-0": { "MyCompany\\MyBundle\\": "" }
    },
    "name": "mycompany/my-bundle",
    "description": "My Bundle",
    "license": "proprietary",
    "repositories": [
        {
            "type": "vcs",
            "url": "git@algithub.pd.mycompany.net:mycompany/custom-framework.git"
        },
        {
            "type": "vcs",
            "url": "git@algithub.pd.mycompany.net:mycompany/ABundle.git"
        },
        {
            "type": "vcs",
            "url": "git@algithub.pd.mycompany.net:mycompany/BBundle.git"
        },
        {
            "type": "vcs",
            "url": "git@algithub.pd.mycompany.net:mycompany/CBundle.git"
        }
    ],
    "require": {
        "mycompany/custom-framework": "dev-development",
        "mycompany/a-bundle":         "dev-development",
        "mycompany/b-bundle":         "dev-development",
        "mycompany/c-bundle":         "dev-development"
    },
    "require-dev": {
        "phpunit/phpunit": "3.7.*",
        "mockery/mockery": "0.9.*"
    },
    "target-dir": "MyCompany/MyBundle"
}

HeavenTest:

<?php
/**
 * @category    My Product
 * @package     Tests
 * @subpackage  Services/Heaven
 * @author      Anonymous <anonymous@mycompany.com>
 * @copyright   Copyright (c) 2014 My Company.
 * @version     0.1
 *
 * */

namespace MyCompany\MyBundle\Tests\Service\Heaven;

use MyCompany\MyBundle\Services\Heaven\Heaven;
use MyCompany\MyBundle\Services\Customer\Customer;
use \Mockery as m;
use Symfony\Bridge\Monolog\Logger;

/**
 * Class HeavenTest, this class is intendeed to make the unit test for the class
 * AlertLogic/MyBundle/Services/Heaven/Heaven
 *
 * @covers MyCompany\MyBundle\Services\Heaven\Heaven
 */
class HeavenTest extends \PHPUnit_Framework_TestCase
{
    /**
     * This method test the correct behavior of the method getHeavensStatusList
     * when no customer is passed as a parameter, it should return an empty array
     *
     * @covers MyCompany\MyBundle\Services\Heaven\Heaven::getHeavensStatusList
     */
    public function testGetHeavensStatusListReturnAnEmptyArray()
    {
        /**
         * Mock of the class that we want to test, and say to the mock that should
         * ommit some methods.
         *
         * @var mock heaven
         */
        $heaven = m::mock("MyCompany\MyBundle\Services\Heaven\Heaven");
        //we dont pass any customer as a parameter
        $returnedArray = $heaven->getHeavensStatusList();

        $this->assertEquals(
            array(),
            $returnedArray,
            'The value returned should be an empty array'
        );
    }

    /**
     * Function to clean up the test.
     * @return void
     */
    protected function tearDown()
    {
        m::close();
    }
}

Heaven:

<?php
/**
 * My Company Heaven Service.
 *
 * @category My Product
 * @package  MyCompanyMyBundle
 * @author   Anonymous <anonymous@mycompany.com>
 */

namespace MyCompany\MyBundle\Services\Heaven;

use MyCompany\ABundle\Services\Heaven\Heaven as CoreHeaven;

/**
 * Class for interacting with Heaven service.
 *
 * @category My Product
 * @package  MyCompanyMyBundle
 * @author   Anonymous <anonymous@mycompany.com>
 */
class Heaven extends CoreHeaven
{
    /**
     * Get a new Heaven Service object
     *
     */
    public function __construct($someParameters)
    {
        // bla bla bla
    }

    /**
     * This function returns an array of heavens uuid with their status.
     *
     * @param int $customerId the customer id
     *
     * @return Array A key value array of containing the heavens status information
     */
    public function getHeavensStatusList($customerId = '')
    {
        if(empty($customerId)){
            return array();
        }

        // bla bla
    }
}

PHPUnit output:

./vendor/bin/phpunit --log-junit=test-results/tests.xml --coverage-clover=test-results/clover.xml --coverage-html=cov/ Tests/Unit
PHPUnit 3.7.37 by Sebastian Bergmann.

Configuration read from /home/automator/projects/mycompany/my_bundle/phpunit.xml.dist

...EE.................

Time: 5.27 seconds, Memory: 15.50Mb

There were 2 errors:

1) MyCompany\MyBundle\Tests\Service\Heaven\HeavenTest::testGetHeavensStatusListReturnAnEmptyArray
BadMethodCallException: Method Mockery_0_MyCompany_MyBundle_Services_Heaven_Heaven::getHeavensStatusList() does not exist on this mock object

/home/automator/projects/mycompany/my_bundle/Tests/Unit/Service/Appliance/ApplianceTest.php:54

2) MyCompany\MyBundle\Tests\Service\Heaven\HeavenTest::testGetHeavensStatusList
BadMethodCallException: Method Mockery_0_MyCompany_MyBundle_Services_Heaven_Heaven::getHeavensStatusList() does not exist on this mock object

/home/automator/projects/mycompany/my_bundle/Tests/Unit/Service/Heaven/HeavenTest.php:127

FAILURES!
Tests: 22, Assertions: 37, Errors: 2.

Generating code coverage report in Clover XML format ... done

Generating code coverage report in HTML format ... done

I don’t know why I keep getting that. As you see, the getHeavensStatusList() method is public, and it DOES exist.

I tried mocking all except for the method I wanted to test, with $heaven = m::mock("MyCompany\MyBundle\Services\Heaven\Heaven[__construct]");, to no avail. Instead I would get this error:

1) MyCompany\MyBundle\Tests\Service\Heaven\HeavenTest::testGetHeavensStatusListReturnAnEmptyArray
Argument 1 passed to Mockery_5_MyCompany_MyBundle_Services_Heaven_Heaven::__construct() must be an instance of Symfony\Component\HttpFoundation\Request, none given

/home/automator/projects/mycompany/my_bundle/vendor/mockery/mockery/library/Mockery/Container.php:432
/home/automator/projects/mycompany/my_bundle/vendor/mockery/mockery/library/Mockery/Container.php:216
/home/automator/projects/mycompany/my_bundle/vendor/mockery/mockery/library/Mockery.php:70
/home/automator/projects/mycompany/my_bundle/Tests/Unit/Service/Heaven/HeavenTest.php:52

Can you spot any error I’ve missed? Thanks in advance for your support.

¿Fue útil?

Solución

THe problem is that you don't create a "partial" mock. If your mock Object should have original functionality (which you want), you need to create a partial mock.

$mock = \Mockery::mock('MyClass')->makePartial();

Usually it is not recommended to mock the class you actually wan't to test but only their dependencies.

But if you are 100% sure that you have the right testing approach just go ahead with partial mocks.

If you get the partial mock working, you probably come accross the issue that your class needs a Request object in the constructor. If you are not using it just pass a new Request or mock a new Request and pass it as constructor argument:

$mock = \Mockery::mock("MyNamespace\MyClass", array(new Request()));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top