PHPUnit和域异常测试

PHPUnit和域异常测试,php,unit-testing,exception,doctrine-orm,phpunit,Php,Unit Testing,Exception,Doctrine Orm,Phpunit,在开发代码的过程中,我给自己带来了一个挑战,因为我认为这不仅是一个很好的实践,特别是对于后端开发人员,而且从长远来看,在构建可伸缩和可扩展的代码方面也有很大帮助 我有一个类,它定义了一系列受支持的条令驱动程序。在这个类中,有一个方法可以创建我的包所支持的任何注释驱动程序的实例 protected $supportedAnnotationDrivers = array( 'Doctrine\ORM\Mapping\Driver\XmlDriver', 'Doctrine\ORM\Mappi

在开发代码的过程中,我给自己带来了一个挑战,因为我认为这不仅是一个很好的实践,特别是对于后端开发人员,而且从长远来看,在构建可伸缩和可扩展的代码方面也有很大帮助

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

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;而且,对于一些见解,我一直感到困惑。所有这些联系都不能让我确信我的做法是正确的

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

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
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
案例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

   ......

   Time: 1.49 seconds, Memory: 3.00Mb

  OK (6 tests, 9 assertions)

 Luyanda.Siko@ZACT-PC301 MINGW64 /d/web/doctrine-bundle
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
例外:条令\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.

我真的很想知道知道我在这里做什么以及我是否做得对的最好方法——如果不是最好的方法的话。也许我试图做的事情甚至不值得,但我相信没有一行代码应该被视为毫无价值和不值得测试。

一般来说,您提供的代码是有效的,并且可以正常工作。您需要抄写您对代码的期望,然后测试您的代码是否满足您的期望

在您的情况下,您希望抛出类型为
\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'
    );
}
/**
 * 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'
    );
}
现在,如果在tested方法中将
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。我会再试一次,如果我满意,回来接受您的回答。再次感谢您抽出时间。