atoum / atoum

The modern, simple and intuitive PHP unit testing framework.
http://atoum.org
Other
1.45k stars 147 forks source link

Unable to mock ext function #815

Open macintoshplus opened 5 years ago

macintoshplus commented 5 years ago

Hi,

I have written the test for a new library needed mock the function provided by a PHP extension (win32service). But the mock not work.

PHP 7.3.0 NTS x64 Atoum v3.3

Test file: https://github.com/win32service/service-library/blob/master/tests/Units/Service/ServiceStateManager.php

<?php
/**
 * This file is part of Win32Service Library package
 * @copy Win32Service (c) 2018
 */

namespace Win32Service\Tests\Units\Service;

use atoum;
use mock;

/**
 * Class ServiceStateManager
 * @package Win32Service\Tests\Units\Service
 * @extensions win32service
 */
class ServiceStateManager extends atoum
{
    public function testChangeState()
    {
        $this->assert('start')
            ->given($this->newTestedInstance())
            ->if($this->function->win32_query_service_status = ['CurrentState'=>WIN32_SERVICE_STOPPED])
            ->and($this->function->win32_start_service = WIN32_NO_ERROR)
            ->then
            ->variable($this->testedInstance->startService(\Win32Service\Model\ServiceIdentifier::identify('servideId')))->isNull
        ;
    }
}

The result: https://ci.appveyor.com/project/macintoshplus/win32servicelib/builds/20977270

> Win32Service\Tests\Units\Service\ServiceStateManager...
[X___________________________________________________________][1/1]
=> Test duration: 0.00 second.
=> Memory usage: 0.00 Mb.
> Total tests duration: 0.00 second.
> Total tests memory usage: 0.15 Mb.
> Running duration: 0.12 second.
Failure (2 tests, 2/2 methods, 0 void method, 0 skipped method, 0 uncompleted method, 0 failure, 0 error, 1 exception)!
> There is 1 exception:
=> Win32Service\Tests\Units\Service\ServiceStateManager::testChangeState():
==> An exception has been thrown in file C:\projects\win32servicelib\tests\Units\Service\ServiceStateManager.php on line 27:
==> Win32Service\Exception\ServiceNotFoundException: Service servideId is not found in C:\projects\win32servicelib\lib\Service\ServiceInformationsTrait.php:67
Stack trace:
#0 C:\projects\win32servicelib\lib\Service\ServiceStateManager.php(91): Win32Service\Service\ServiceStateManager->checkResponseAndConvertInExceptionIfNeed(1060, Object(Win32Service\Model\ServiceIdentifier))
#1 C:\projects\win32servicelib\lib\Service\ServiceStateManager.php(29): Win32Service\Service\ServiceStateManager->actionForService(Object(Win32Service\Model\ServiceIdentifier), 'win32_start_ser...', 'isStopped')
#2 C:\projects\win32servicelib\tests\Units\Service\ServiceStateManager.php(27): Win32Service\Service\ServiceStateManager->startService(Object(Win32Service\Model\ServiceIdentifier))
#3 C:\projects\win32servicelib\vendor\atoum\atoum\classes\test.php(1363): Win32Service\Tests\Units\Service\ServiceStateManager->testChangeState()
#4 Standard input code(1): mageekguy\atoum\test->runTestMethod('testChangeState')
#5 {main}

Link to the library: https://github.com/win32service/service-library/

Can you help me ?

Grummfy commented 5 years ago

the two function seems correct. did you test a simple call to the function to validate that it's this function that are not working?

macintoshplus commented 5 years ago

The function call is:

$result = $action($serviceId->serviceId(), $serviceId->machine());

$action contains the name of function does be call.

Source: https://github.com/win32service/service-library/blob/master/lib/Service/ServiceStateManager.php#L89

macintoshplus commented 5 years ago

If I replace the line with a switch case, the mock work finely:

//$result = $action($serviceId->serviceId(), $serviceId->machine());
switch ($action) {
            case 'win32_start_service':
                $result = win32_start_service($serviceId->serviceId(), $serviceId->machine());
                break;

            case 'win32_stop_service':
                $result = win32_stop_service($serviceId->serviceId(), $serviceId->machine());
                break;

            case 'win32_pause_service':
                $result = win32_pause_service($serviceId->serviceId(), $serviceId->machine());
                break;

            case 'win32_continue_service':
                $result = win32_continue_service($serviceId->serviceId(), $serviceId->machine());
                break;

            default:
                # code...
                break;
        }

But it's not optimized...