【问题标题】:PHPUnit and Domain Exception TestingPHPUnit 和域异常测试
【发布时间】:2016-04-27 09:25:45
【问题描述】:

我给自己一个挑战,在开发代码时使用测试代码,因为我认为这不仅是一种很好的做法,尤其是对于后端开发人员来说,而且在构建可扩展和可扩展的代码方面也有很大帮助。从长远来看。

我有一个类定义了一系列受支持的学说驱动程序。在这个类中,有一个方法可以创建我的包支持的任何注释驱动程序的实例。

protected $supportedAnnotationDrivers = array(
  'Doctrine\ORM\Mapping\Driver\XmlDriver',
  'Doctrine\ORM\Mapping\Driver\YamlDriver',
  'Doctrine\ORM\Mapping\Driver\AnnotationDriver'
 );

创建这些驱动程序的任何实例的方法如下所示:

 public function getAnnotationDriver($classDriver, $entityDriver)
 {
     if(!in_array($classDriver, $this->supportedAnnotationDrivers)){
        throw new \RuntimeException(sprintf(
           "%s is not a supported Annotation Driver.", $classDriver
          ));           
        }

      if('Doctrine\ORM\Mapping\Driver\AnnotationDriver' === $classDriver){
           $annotationDriver = new $classDriver(new AnnotationReader(), array($entityDriver));
           AnnotationRegistry::registerLoader('class_exists');
         }else{
          $annotationDriver = new $classDriver($entityDriver);
       }

      return $annotationDriver; 
     }

在我继续之前,我不得不说我已经查阅了 PHPUnit 手册和 StackOverflow,here; here; herethere ,对于一些见解,但我一直很困惑。而且这些链接都不能让我确定我正在以正确的方式进行。

下面是我的测试类中的测试函数:

public function testUnsupportedAnnotationDriverException()
{
     try{

        $entityManagerService = new EntityManagerService();

         //Client requests a unsupported driver
         $unsupportedDriver              = 'Doctrine\ORM\Mapping\Driver\StaticPHPDriver';
         $actualUnsupportedException     = $entityManagerService->getAnnotationDriver(
         $unsupportedDriver, __DIR__ . '/../../Helper'
       );
      }catch(\RuntimeException $actualUnsupportedException){
        return;
     }

    $this->fail('An expected exception has not been raised!.');
  }

当谈到这部分时,我真的很困惑。在我的测试中,我使用了一个由我的代码引发的异常,即 RuntimeException 并且我的测试通过了。当我将客户端代码更改为仅抛出异常但让我的测试保持原样时,它会失败并从客户端代码中抛出异常。我很高兴知道我的测试失败了,因为我的测试中抛出的异常给了我在用户通过不受支持的驱动程序时我希望得到的结果。

但是,在测试异常时,我缺少注释用法和 $this->fail("text/for/failer/) 函数的上下文。

我怎样才能最好地为此方法编写测试?我所做的正是测试应该如何表现,也许是我没有掌握 PHPUnit 这部分背后的概念?下面是我从 PHPUnit 得到的输出:

案例 1:测试和客户端代码中的异常相同

Luyanda.Siko@ZACT-PC301 MINGW64 /d/web/doctrine-bundle
$ vendor/bin/phpunit
  PHPUnit 3.7.38 by Sebastian Bergmann.

   Configuration read from D:\web\doctrine-bundle\phpunit.xml

   ......

   Time: 1.49 seconds, Memory: 3.00Mb

  OK (6 tests, 9 assertions)

 Luyanda.Siko@ZACT-PC301 MINGW64 /d/web/doctrine-bundle

案例 2:测试和客户端代码中的异常不同

Luyanda.Siko@ZACT-PC301 MINGW64 /d/web/doctrine-bundle
 $ vendor/bin/phpunit
   PHPUnit 3.7.38 by Sebastian Bergmann.

   Configuration read from D:\web\doctrine-bundle\phpunit.xml

   ..E...

   Time: 1.59 seconds, Memory: 3.00Mb

   There was 1 error:

 1)   PhpUnitBundle\Unit\ApplicationContext\Service\EntityManagerServiceTest::testUnsupportedAnnotationDriverException

例外:Doctrine\ORM\Mapping\Driver\StaticPHPDriver 不是受支持的注释驱动程序。

 D:\web\doctrine-bundle\lib\DoctrineBundle\ApplicationContext\Service\EntityManagerService.php:33
 D:\web\doctrine-bundle\lib\PhpUnitBundle\Unit\ApplicationContext\Service\EntityManagerServiceTest.php:68

 FAILURES!
 Tests: 6, Assertions: 9, Errors: 1.

我真的很想知道最好的方法来了解我在这里做什么以及我是否做得对 - 如果不是最好的方法。 Perpahs 我正在尝试做的事情甚至不值得,但我相信任何一行代码都不应该被视为毫无价值和不值得测试。

【问题讨论】:

    标签: php unit-testing exception doctrine-orm phpunit


    【解决方案1】:

    一般来说,您提供的代码是有效的并且可以正常工作。您描述您对代码的期望,然后测试您的代码是否符合您的期望。

    在您的情况下,您预计会抛出 \RuntimeException 类型的异常,如果它只是 \Exception - 则会出现错误

    另一个问题是phpunit 是如何告诉你的。在您的情况下,它显示消息

    1)   PhpUnitBundle\Unit\ApplicationContext\Service\EntityManagerServiceTest::testUnsupportedAnnotationDriverException
    Exception: Doctrine\ORM\Mapping\Driver\StaticPHPDriver is not a supported Annotation Driver.
    

    不是很明显。 如果使用setExpectedException 描述期望,您可以更明确地表达期望:

    /**
     * Test fail if client requests a unsupported driver
     */
    public function testUnsupportedAnnotationDriverException()
    {
        $entityManagerService = new EntityManagerService();
    
        $this->setExpectedException(\RuntimeException::class);
        // $this->setExpectedException('RuntimeException'); // for PHP < 5.5
    
        $unsupportedDriver = 'Doctrine\ORM\Mapping\Driver\StaticPHPDriver';
        $actualUnsupportedException = $entityManagerService->getAnnotationDriver(
            $unsupportedDriver, __DIR__ . '/../../Helper'
        );
    }
    

    或使用适当的注释@expectedException:

    /**
     * Test fail if client requests a unsupported driver
     *
     * @expectedException \RuntimeException
     */
    public function testUnsupportedAnnotationDriverException()
    {
        $entityManagerService = new EntityManagerService();
    
        $unsupportedDriver = 'Doctrine\ORM\Mapping\Driver\StaticPHPDriver';
        $actualUnsupportedException = $entityManagerService->getAnnotationDriver(
            $unsupportedDriver, __DIR__ . '/../../Helper'
        );
    }
    

    现在如果你在测试方法中将throw \RuntimeException 更改为throw \Exception,你可以注意到phpunit 的消息现在看起来像这样

    Failed asserting that exception of type "Exception" matches expected exception "\RuntimeException". Message was: "Doctrine\ORM\Mapping\Driver\StaticPHPDriver is not a supported Annotation Driver." 
    

    所以你会更清楚地看到哪里出了问题

    【讨论】:

    • 感谢@SmoothAF。我会再试一次,如果我满意,我会回来接受你的回答。再次感谢您的宝贵时间。
    猜你喜欢
    • 1970-01-01
    • 2014-07-07
    • 2015-10-17
    • 1970-01-01
    • 2011-03-29
    • 2012-03-20
    • 2018-03-31
    • 2020-12-21
    • 1970-01-01
    相关资源
    最近更新 更多