23

単体テストについて学んでいて、次の問題を解決しようとしました。

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication

...で与えられた唯一の答えを使用して:

ZfcUser を使用したコントローラーの単純な ZF2 単体テスト

したがって、私のsetUp関数は同じように見えます。残念ながら、次のエラー メッセージが表示されます。

Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAuthentication_868bf824 is invalid; must implement Zend\Mvc\Controller\Plugin\PluginInterface

コードのこの部分で発生します(私のコードでも同じように分割されています):

$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock); // Error refers to this line.

$authMock オブジェクトは、setService に渡すために実装する必要がある plugininterface を実装していないようです。

$authMock は、単体テストで使用するためにそこに渡されることを意図していませんか? 別の (単体テスト指向の) setService メソッドを使用する必要がありますか?

アプリケーションへのログインを処理する方法が必要です。そうしないと、単体テストが無意味になります。

アドバイスをありがとう。

=== 編集 (2013/11/02) ===

これが問題の領域だと思うので、明確にするためにこの部分に焦点を当てたいと思いました:

// Getting mock of authentication object, which is used as a plugin.
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication');

// Some expectations of the authentication service.
$authMock   -> expects($this->any())
    -> method('hasIdentity')
    -> will($this->returnValue(true));  

$authMock   -> expects($this->any())
    -> method('getIdentity')
    -> will($this->returnValue($ZfcUserMock));

// At this point, PluginManager disallows mock being assigned as plugin because 
// it will not implement plugin interface, as mentioned.
$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);

モックが必要な実装を処理しない場合、他にどのようにログインするふりをすることができますか?

4

2 に答える 2

3

名前空間またはオートローダーに問題があります。

モックを作成しているときに、のクラス定義ZfcUser\Controller\Plugin\ZfcUserAuthenticationが見つかりません。したがって、PHPUnit は、テスト用にこのクラスのみを拡張するモックを作成します。クラスが利用可能な場合、PHPUnit はモックを作成するときに実際のクラスを使用して拡張し、その後、親クラス/インターフェースを使用します。

このロジックはこちらで確認できます: https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/PHPUnit/Framework/MockObject/Generator.php

    if (!class_exists($mockClassName['fullClassName'], $callAutoload) &&
        !interface_exists($mockClassName['fullClassName'], $callAutoload)) {
        $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n";

        if (!empty($mockClassName['namespaceName'])) {
            $prologue = 'namespace ' . $mockClassName['namespaceName'] .
                        " {\n\n" . $prologue . "}\n\n" .
                        "namespace {\n\n";

            $epilogue = "\n\n}";
        }

        $cloneTemplate = new Text_Template(
          $templateDir . 'mocked_clone.tpl'
        );

したがって、クラスまたはインターフェースがない場合、PHPUnit は実際にそれ自体を作成し、モックが元のクラス名の型ヒントを満たすようにします。ただし、PHPUnit はそれらを認識しないため、親クラスまたはインターフェイスは含まれません。

これは、テストに適切な名前空間が含まれていないか、オートローダーに問題があることが原因である可能性があります。テスト ファイル全体を実際に見ないとわかりません。


をモックする代わりに、テストでZfcUser\Controller\Plugin\ZfcUserAuthenticationをモックZend\Mvc\Controller\Plugin\PluginInterfaceしてプラグイン マネージャーに渡すこともできます。ただし、コードでプラグインのタイプヒントを使用している場合でも、テストは機能しません。

//Mock the plugin interface for checking authorization
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface');

// Some expectations of the authentication service.
$authMock   -> expects($this->any())
    -> method('hasIdentity')
    -> will($this->returnValue(true));  

$authMock   -> expects($this->any())
    -> method('getIdentity')
    -> will($this->returnValue($ZfcUserMock));

$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);
于 2014-01-15T14:54:26.710 に答える