【问题标题】:PHPUnit - test autoloader classPHPUnit - 测试自动加载器类
【发布时间】:2011-09-20 16:54:27
【问题描述】:

我需要为我的应用程序创建一个自动加载器。我不想依赖文件系统中的文件,那么如何模拟新调用?或者你如何测试一个自动加载器类? 谢谢。

【问题讨论】:

    标签: php mocking phpunit autoload spl-autoload-register


    【解决方案1】:

    或者你如何测试一个自动加载器类

    恕我直言,您根本不需要对自动加载器进行单元测试。

    如果你引导你的应用程序,它会非常严重地崩溃,因为它可以找到所有需要的类,或者你的自动加载器工作正常。

    你的测试套件中的每一个测试都会测试自动加载器是否能够加载“被测类”,所以我不会太担心单元测试。

    如果您愿意,可以将其称为“作为副作用的集成测试”,但我认为这已经足够了。

    如果您认为这还不够好,我会将 require/include 语句放在受保护的函数中,并在测试自动加载器中覆盖该函数并检查它是否接收到正确的值。

    【讨论】:

      【解决方案2】:

      创建一些专门用于测试自动加载器的类文件,并将它们放在一个单独的目录中(与测试同级),您可以在该目录中注册自动加载器。使用class_exists($class, false) 测试是否在不调用自动加载器的情况下加载了一个类。

      注意:如果您将自动加载器设计为非静态的,这样您就可以为测试实例化一个单独的实例而不是测试活动的实例,这会有所帮助。

      以下是以我的自定义自动加载器的autoload() 方法的测试为例:

      function test_autoload_loadsExistingClass() {
          $this->fixture->registerPrefix('TestClasses', self::$root . 'models');
          if (class_exists('TestClasses_Autoloader_Foo', false)) {
              self::error('Class TestClasses_Autoloader_Foo is already loaded');
          }
          $this->fixture->autoload('TestClasses_Autoloader_Foo');
          if (!class_exists('TestClasses_Autoloader_Foo', false)) {
              self::fail('Class TestClasses_Autoloader_Foo failed to load');
          }
      }
      
      function test_autoload_silentlyIgnoresMissingClasses() {
          $this->fixture->registerPrefix('Foo', self::$root . 'models');
          $this->fixture->autoload('Foo_Bar');
      }
      
      function test_autoload_searchesIncludePathForUnknownPrefix() {
          if (class_exists('TestClasses_Autoloader_Foo', false)) {
              self::error('Class TestClasses_Autoloader_Foo is already loaded');
          }
          set_include_path(self::$root . 'include' . PATH_SEPARATOR . self::$savedIncludePath);
          $this->fixture->autoload('TestClasses_Autoloader_Foo');
          if (!class_exists('TestClasses_Autoloader_Foo', false)) {
              self::fail('Class TestClasses_Autoloader_Foo failed to load');
          }
      }
      

      更新:哇,我不知道我是怎么错过你的问题中的“我不想依赖文件系统中的文件”,但这很关键。您需要在自动加载器自己的方法中调用include(例如includeFile($path))。这将允许您在测试期间模拟该方法,因此您不涉及磁盘上的文件。除此之外,您可以像往常一样测试该类:向其提供要自动加载的类的输入(如上所述),并验证您的类在应该使用正确路径时调用 includeFile()

      function testAutoloadLoadsExistingClass() {
          $fixture = $this->getMock('MyAutoloader', 
                  array('includeFile'),  // mock the call to `include`
                  array(...));           // constructor args
          $fixture->expects($this->once())
                  ->method('includeFile')
                  ->with('My/Package/Class')
                  ->will($this->returnValue(true));
          self::assertTrue($fixture->autoload('My_Package_Class'));
      }
      

      【讨论】:

        【解决方案3】:

        如何测试自动加载器类?

        取决于自动加载器类的作用。例如,您可以测试注册自动加载回调是否适用于spl_autoload_register

        或者,如果您的自动加载器提供了一个 LoadLibrary 函数来加载库的所有类和接口,以检查是否所有类都已加载。但这通常取决于文件系统(我认为这没问题)。

        【讨论】:

          猜你喜欢
          • 2014-10-02
          • 1970-01-01
          • 2015-09-05
          • 2023-03-29
          • 2019-07-09
          • 2012-02-13
          • 2017-06-13
          • 2013-04-13
          • 1970-01-01
          相关资源
          最近更新 更多