PHPUnit 3.7.19 和 Symfony2 破坏测试 [英] PHPUnit 3.7.19 and Symfony2 broken tests

查看:17
本文介绍了PHPUnit 3.7.19 和 Symfony2 破坏测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 Symfony2.0 项目开发一些测试并使用 PHPUnit 运行它们.

I'm developing some test for a Symfony2.0 project and running them with PHPUnit.

在我的 PC 上工作正常,但在其他环境中尝试测试失败.我以为问题出在 php 版本上,但在不同的环境中运行它们后我迷路了.

On my PC works fine but trying them in other environments the tests fails. I thought the problem was php version but after run them in differents environments I'm lost.

  • 我的环境是 Ubuntu 12.04 和 PHP 5.3.10 => 工作正常.

2 台装有 Ubuntu 12.10 和 PHP 5.4.6 的电脑:

2 PC with Ubuntu 12.10 and PHP 5.4.6:

Fatal error:  Call to a member function get() on a non-object

这个错误出现在一个扩展了 SymfonyBundleFrameworkBundleTestWebTestCase 的类上,该类被覆盖了 setUp() 和 tearDown() 方法.

This error is on a class which extends SymfonyBundleFrameworkBundleTestWebTestCase where is overwritten the setUp() and tearDown() methods.

public function setUp()
{
    $this->client = static::createClient();
    $this->client->followRedirects(true);

    $crawler = $this->client->request('GET', '/admin/login');

    $loginForm = $crawler->selectButton('save')->form(array(
        '_username' => 'user',
        '_password' => 'pass'
        ));
    $this->client->submit($loginForm);

    $this->container = $this->client->getContainer();
    parent::setUp();
}

public function tearDown()
{
    //Here is get() on a non-object, $this->container doesn't exists
    $this->container->get('doctrine.odm.mongodb.document_manager')->getConnection()->close();
    parent::tearDown();
}

  • 2 台 PC,一台装有 Ubuntu 12.10 和 PHP 5.4.6,另一台装有 Windows 7 和 PHP 5.3.8:

    • 2 PC, one with Ubuntu 12.10 and PHP 5.4.6 and other with Windows 7 and PHP 5.3.8:

      PHP Fatal error:  Call to a member function getSite() on a non-object
      

    • 此错误出现在扩展上述类的类上,该类的 tearDown() 方法错误,但在这种情况下,该类有效,错误不同,尽管与 $this->container 相关:

      This error is on a class which extends the above class that has tearDown() method wrong but in this case this class works and the error is different although is related with $this->container:

      //In this case, the user doesn't exists
      $site = $this->container->get('security.context')
              ->getToken()->getUser()->getSite();
      

      问题是我不知道这是为什么.如果这和PHP有关,PHPUnit(我们都有相同的版本),Symfony2.0或SO.

      The problem is I don't know why is this. If this is related to PHP, PHPUnit(All of us have the same version), Symfony2.0 or SO.

      好的,问题解决了.

      第一:

      Fatal error:  Call to a member function get() on a non-object
      

      在具有 setUp() 和 tearDown() 方法的类中有错误的代码行.像这样的一行:

      Had a wrong line of code in the class which has setUp() and tearDown() methods. A line like that:

      $link = $crawler->filter('a:contains("Test")')->eq(1)->link();
      

      我已经评论了这行,抱歉 :).但我不知道为什么 PHPUnit 显示这个错误而不是链接方法的错误.

      I had this line commented, sorry :). But I don't know why PHPUnit show me this error and not the error of link method.

      第二:

      PHP Fatal error:  Call to a member function getSite() on a non-object
      

      在其他环境中,测试数据库尚未部署.

      In the others environments, the test database had not been deployed.

      这个问题不会帮助任何人,但会帮助我尝试新事物.谢谢!

      This question will not help anyone but help me to try new things. Thanks!

      推荐答案

      这是 PHPUnit 的一种执行行为.

      It is an exected behavior for PHPUnit.

      我设法用以下代码重现了错误:

      I managed to reproduce the error with the following code:

      final class ExceptionErrorTest extends PHPUnit_Framework_TestCase
      {
          /**
           * @var MyObject
           */
          private $object;
      
          public function setUp() {
              throw new RuntimeException();
              $this->object = new MyObject();
          }
      
          public function testItShouldNeverBeCalled()
          {
              var_dump('never called');
          }
      
          public function tearDown()
          {
              $this->object->neverCalled();
          }
      }
      
      class MyObject
      {
          public function neverCalled() {
              return true;
          }
      }
      
      // will ouput PHP Fatal error: 
      Call to a member function neverCalled() on a non-object in ExceptionErrorTest.php on line 22
      

      为了解释得更清楚,PHPUnit会catch setUp 方法中触发的任何异常(为了让打印机在执行结束时显示).

      To explain more clearly, PHPUnit will catch any exceptions triggered in the setUp method (in order for the printers to show at the end of the execution).

      之后,您可以看到调用 tearDown() 来完成测试,但由于从未达到属性的初始化,因此发出 PHP 错误,并且 PHPUnit 永远不会到达显示所有发生的异常的代码.

      After that you can see that the tearDown() is called to finish the test, but since the initialization of the attribute was never reached, a PHP error is issued, and PHPUnit will never reach the code where it shows all the exceptions that occurred.

      这就是你没有得到异常的原因.要解决此问题,您需要确保任何可以在设置中引发异常的代码都包含在 try() catch () 语句中,如下所示:

      That is why you did not get the exception. To fix this, you need to make sure that any code that can throw exceptions in the setup is wrapped in a try() catch () statement like this:

          public function setUp() {
              try {
                  throw new RuntimeException('My message');
              } catch (Exception $e) {
                  echo 'An error occured in the setup: ' $e->getMessage();
                  die;
              }
      
              $this->object = new MyObject();
          }
      

      希望它对未来的人有所帮助.

      Hope it helps someone in the future.

      这篇关于PHPUnit 3.7.19 和 Symfony2 破坏测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆