somemo programming etc.

プログラマ、雑記、プログラミング関係はLinkから、数式はこっちでまとめていることが多い

【php】シングルトンのテスト【PHPUnit】

会社にあるPHPデザパタ本で勉強を始めました。

書籍ではWEB上での確認ですが、自分はテストコードを使うことにしました。

シングルトンの理解については特に問題ないのですが、cloneの防止や例外のテストが勉強になりました。

<?php
class SingletonSample {
  
  /**
   * 自身のクラスを保持するメンバ変数
   * @var SingletonSample
   */
  private static $instance;
  
  /**
   * ID
   * @var String
   */
  private $id;
  
  /**
   * コンストラクタ
   */
  private function __construct() {
    $this->id = md5(date('r'). mt_rand());
  }
  
  /**
   * インスタンスの取得
   */
  public static function getInstance() {
    
    if (!isset(self::$instance)) {
      self::$instance = new SingletonSample();
      echo 'create';
    };
    
    return self::$instance;
  }
  
  /**
   * IDの取得
   */
  public function getId() {
    return $this->id;
  }
  
  /**
   * clone防止
   */
  public final function __clone() {
    throw new RuntimeException('Clone is not allowed against '. get_class($this));
  }
}
<?php
require_once dirname(__FILE__).'/../../src/singleton/SingletonSample.class.php';
class SingletonTest extends PHPUnit_Framework_TestCase {

  private $instance1;
  private $instance2;
  
  public function setUp() {
    $this->instance1 = SingletonSample::getInstance();
    $this->instance2 = SingletonSample::getInstance();
    
  }
  
  /**
   * インスタンスのIDが同一であることをテストする
   */
  public function testSameId() {
    $this->assertTrue($this->instance1->getId() === $this->instance2->getId());
  }
  
  /**
   * インスタンスが同一であることをテストする
   */
  public function testSameInstance() {
    $this->assertTrue($this->instance1 === $this->instance2);
  }
  
  /**
   * インスタンスのコピーを生成できないようにする
   */
  public function testDisableClone() {
    try {
      $instance_copy = clone $this->instance1;
    } catch (Exception $e) {
      return;
    }
    
    $this->fail('able copy');
  }
}

追記:インスタンスコピー防止のテストの修正しました。5tests、4assertionsになっていました・・・。

  /**
   * インスタンスのコピーを生成できないようにする
   */
  public function testDisableClone() {
    try {
      $instance_copy = clone $this->instance1;
      $this->fail('able copy');
    } catch (Exception $e) {
      $this->assertTrue(true);
     // または、assertTrueに渡す引数を変数化して、try-catchブロックの外で判定する
    }
  }
}