PHPUnit:致命错误


PHPUnit: Fatal error Class ClassName not found

我正在尝试为CodeIgniter应用程序构建一个单元测试环境。我遵循这本书,让PHPUnit工作。

我正在测试模型中的一些代码:

    public function testPresent()
{
    $tracker = new Tracker_model();
    $tableObj = (object)array( 'type' => $this->expectedConstants['TABLE']);
    $visitsObj = (object)array( 'type' => $this->expectedConstants['VISITS']);
    $tableObj = $tracker->present($tableObj);
    $visitsObj = $tracker->present($visitsObj);
    $this->assertThat($tableObj, $this->isInstanceOf('Tracker_TablePresenter'));
    $this->assertThat($visitsObj, $this->isInstanceOf('Tracker_VisitsPresenter'));
}

测试的代码如下:

    public function present($obj)
{
    if( isset($obj->type) )
    {
        switch($obj->type)
        {
            case self::VISITS: $type = 'Visits'; break;
            case self::TABLE: 
            default: $type = 'Table'; break;
        }
        $className = 'Tracker_'.$type.'Presenter';
        $obj = new $className($obj, 'tracker');
    }
    return $obj;
}

它应该加载在文件presenters/tracker/TablePresenter.php中的类Tracker_TablePresenter。我无法解释这种机制背后的所有逻辑,因为它太长太复杂,但我知道它是有效的,因为在另一台计算机上使用完全相同的代码,它通过了测试。相反,在我的计算机上,我得到这个错误:

.......PHP Fatal error:  Class 'Tracker_TablePresenter' not found in /home/.../application/models/tracker_model.php on line 42

关于错误的更多信息:

PHP Stack trace:
PHP   1. {main}() /.../vendor/phpunit/phpunit/composer/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /.../vendor/phpunit/phpunit/composer/bin/phpunit:63
PHP   3. PHPUnit_TextUI_Command->run() /.../vendor/phpunit/phpunit/PHPUnit/TextUI/Command.php:129
PHP   4. PHPUnit_TextUI_TestRunner->doRun() /.../vendor/phpunit/phpunit/PHPUnit/TextUI/Command.php:176
PHP   5. PHPUnit_Framework_TestSuite->run() /.../vendor/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php:349
PHP   6. PHPUnit_Framework_TestSuite->run() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:705
PHP   7. PHPUnit_Framework_TestSuite->runTest() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:745
PHP   8. PHPUnit_Framework_TestCase->run() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:775
PHP   9. PHPUnit_Framework_TestResult->run() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:776
PHP  10. PHPUnit_Framework_TestCase->runBare() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestResult.php:648
PHP  11. PHPUnit_Framework_TestCase->runTest() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:831
PHP  12. ReflectionMethod->invokeArgs() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:976
PHP  13. Tracker_modelTest->testPresent() /.../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:976
PHP  14. Tracker_model->present() /.../application/tests/models/Tracker_modelTest.php:38

我在Ubuntu上工作,而另一个让代码工作的人使用的是Mac。这是我的php -v

的输出
PHP 5.4.9-4ubuntu2 (cli) (built: Mar 11 2013 16:09:26) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
with Xdebug v2.3.0dev, Copyright (c) 2002-2013, by Derick Rethans

我也尝试将php降级到5.3,因为他正在使用5.3,但没有。同样的错误。你能帮我弄明白这是怎么回事吗?

编辑:

TablePresenter.php

文件的内容
<?php
class Tracker_TablePresenter extends Presenter
{
public function values()
{
    $this->ci =& get_instance();
    if (!isset($this->values)) {
        $this->ci->load->model('value_model', 'value');
        $this->values = $this->ci->value->getManyForTracker($this->tracker->id);
    }
    return $this->values;
}
}
?>
编辑2:

我按照JoDev的建议更改了present函数中的代码,如下所示:

    public function present($obj)
{
if( isset($obj->type) )
{
    switch($obj->type)
    {
        case self::VISITS: $type = 'Visits'; break;
        case self::TABLE: 
        default: $type = 'Table'; break;
    }
    //use include, but require is to force an internal error if the file isn't founded!
    require_once('presenters/tracker/'.$type.'Presenter.php');
    $className = 'Tracker_'.$type.'Presenter';
    $obj = new $className($obj, 'tracker');
}
return $obj;
}

现在我得到这个错误:

PHPUnit 3.7.21 by Sebastian Bergmann.
Configuration read from .../phpunit.xml
.......PHP Fatal error:  Class 'Tracker_TablePresenter' not found in .../application/models/tracker_model.php on line 61
PHP Stack trace:
PHP   1. {main}() .../vendor/phpunit/phpunit/composer/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() .../vendor/phpunit/phpunit/composer/bin/phpunit:63
PHP   3. PHPUnit_TextUI_Command->run() .../vendor/phpunit/phpunit/PHPUnit/TextUI/Command.php:129
PHP   4. PHPUnit_TextUI_TestRunner->doRun() .../vendor/phpunit/phpunit/PHPUnit/TextUI/Command.php:176
PHP   5. PHPUnit_Framework_TestSuite->run() .../vendor/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php:349
PHP   6. PHPUnit_Framework_TestSuite->run() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:705
PHP   7. PHPUnit_Framework_TestSuite->runTest() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:745
PHP   8. PHPUnit_Framework_TestCase->run() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php:775
PHP   9. PHPUnit_Framework_TestResult->run() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:776
PHP  10. PHPUnit_Framework_TestCase->runBare() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestResult.php:648
PHP  11. PHPUnit_Framework_TestCase->runTest() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:831
PHP  12. ReflectionMethod->invokeArgs() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:976
PHP  13. Tracker_modelTest->testPresent() .../vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php:976
PHP  14. Tracker_model->present() .../application/tests/models/Tracker_modelTest.php:37

<h4>A PHP Error was encountered</h4>
<p>Severity: Warning</p>
<p>Message:  include(presenters/tracker/TablePresenter.php): failed to open stream: No such file or directory</p>
<p>Filename: models/tracker_model.php</p>
<p>Line Number: 58</p>
</div><div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">
<h4>A PHP Error was encountered</h4>
<p>Severity: Warning</p>
<p>Message:  include(): Failed opening 'presenters/tracker/TablePresenter.php' for inclusion (include_path='.../vendor/phpunit/php-text-template:.../vendor/phpunit/phpunit-mock-objects:.../vendor/phpunit/php-timer:.../vendor/phpunit/php-token-stream:.../vendor/phpunit/php-file-iterator:.../vendor/phpunit/php-code-coverage:.../vendor/phpunit/phpunit:.../vendor/symfony/yaml:.../vendor/pdepend/pdepend/src/main/php:.../vendor/phpmd/phpmd/src/main/php:.:/usr/share/php:/usr/share/pear')</p>
<p>Filename: models/tracker_model.php</p>
<p>Line Number: 58</p>
</div>%                       

请尝试使用:

public function present($obj)
{
    if( isset($obj->type) )
    {
        switch($obj->type)
        {
            case self::VISITS: $type = 'Visits'; break;
            case self::TABLE: 
            default: $type = 'Table'; break;
        }
        //use include, but require is to force an internal error if the file isn't founded!
        require_once('Presenters/Tracker/'.$type.'Presenter.php');
        $className = 'Tracker_'.$type.'Presenter';
        $obj = new $className($obj, 'tracker');
    }
    return $obj;
}

感谢这个测试,你将能够知道如果错误是在autoloader或其他任何地方!告诉我还有什么…

[编辑@13/06/2013 10:00]

在树中调用TablePresenter的文件在哪里?

要解决这个问题,你有(在我看来)三种可能性:
-1)在服务器的include_path中添加Presenter的父目录!(要检索实际包含,使用get_include_path())
-2)确保使用好的URL包含文件
-3)使用绝对URL

我打赌这与你机器上的文件权限有关。脚本无法找到文件,因为Apache无法打开它。

听起来像是一个区分大小写的问题(@jospratik的问题)。据我所知,OSX不区分大小写。所以这是你在linux和mac/win上工作时会遇到的问题。

将文件夹名称更改为以大写字符开头,如

Presenters/Tracker/VisitsPresenter.php

对我来说似乎是一个问题与类'Tracker_TablePresenter'找不到。您是否使用了正确的名称空间?