ci-phpunit-testを使う時に知っておいて欲しいCodeIgniter3の実装-依存性解決の実装
Tweet私はしばし、ci-phpunit-testを使ったテストの書き方で、CodeIgniter3自体の挙動を説明しなければならないことがあります。
私は、その説明が非常にめんどくさいと感じているのでここに記載します。
知っておいて欲しい実装は次の4つです。
- Controllerの実装(設計)
- Controllerの実装(コンストラクタ)
- 依存性解決の実装 <- イマココ
- Modelの実装
依存性解決の実装
前回までの内容で、CodeIgniterではControllerインスタンスを共通化しやすい構造になっていると記載しましたが、
CodeIgniterではController以外にもLibraryやModel等のインスタンス(依存性)も共通化しやすい構造になっています。
その構造に大きく関係するのがload_class
関数とLoader
クラスです。
load_class
関数の実装
load_class関数はLibraryやsystem/coreディレクトリのクラスを読み込んでそのインスタンスを返します。
このとき、読み込んだクラスのインスタンスは共通化しやすい様に関数内部に保持されます。
つまり、次のようになります。
1 |
|
読み込みのロジックはLoader::modelやLoader::libraryとは異なり、Libraryやsystem/coreディレクトリのクラスを読み込むために利用されています。
そのため、フレームワーク利用者が触ることはほとんどありません。
またsystem/core内のLoaderクラスもこのload_class関数を利用して読み込まれます。
Loader::modelとLoader::libraryの実装
Loader::modelとLoader::libraryも同様にLibraryやModelクラスのインスタンスを共通化しやすい様に作られています。
何度ロードしてもControllerのプロパティに定義されているインスタンスは同じインスタンスです。
1 |
|
ただし、既にロード済みの依存性をLoader::libraryやLoader::modelでロードした場合プロパティ名とインスタンス名が異なるとエラーが発生します。
プロパティ名とインスタンス名とは、正確にはinstanceof
演算子でチェックしています。
そのため、継承関係にある場合はエラーは発生しません。
1 |
|
また、Loader::modelの場合は、Loader::modelを利用してプロパティに依存性を注入していない限り同じインスタンス名であってもエラーが発生します。
1 |
|
ここまでのまとめ
- load_class関数はLibraryやsystem/coreディレクトリのクラスを読み込むために利用されている。
- Loader::model、Loader::library実行時はinstanceofでインスタンス名がチェックされている。
- Loader::modelはLoader::modelを利用せずにプロパティに代入されているとエラーが発生する。
テスト時に知っておきたいこと
load_class関数はLibraryやsystem/coreディレクトリのクラスを読み込むために利用されている
load_class関数はLibraryやsystem/coreディレクトリのクラスを読み込むために利用されています。
ci-phpunit-testにはload_class_instance関数があります。
そのため、CodeIgniterのsystem/coreに定義されたクラスファイルのモック化もある程度は可能です。
CodeIgniterの中でload_class関数を利用して読み込まれているクラスは以下の通りです。
- Benchmark
- Hooks
- Config
- Utf8
- URI
- Router
- Output
- Security
- Input
- Lang
- Loader
これらのcoreクラスをMockオブジェクトに書き換えているテストが以下です。
テスト対象のコントローラ1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Sample extends CI_Controller
{
const APP_KEY = '42qj0j@vpq33-[29hgvaegh38';
public function __construct()
{
parent::__construct();
$app_key = $this->input->cookie('app-key');
if ($app_key !== self::APP_KEY) {
show_error('APP KEYが誤っています。');
}
}
public function index()
{
$this->load->view('sample');
}
}
テストコード
1 |
|
Loader::model、Loader::library実行時はinstanceofでインスタンス名がチェックされている
Loader::model、Loader::library実行時はinstanceofでインスタンス名がチェックされます。
そのため、以下の様なテストをするときは注意が必要です。
1 |
|
1 |
|
上の例では、正しくは、MY_Form_validation
のmockオブジェクトを作成する様にします。
Loader::modelはLoader::modelを利用せずにプロパティに代入されているとエラーが発生する
さきほどと打って変わって、Loader::modelでは同じインスタンスであっても注入の経路によってエラーが発生します。
1 |
|
1 |
|