2017-05-30 6 views
0

にプロパティを設定するためにリフレクションを使用することは、私のシナリオです:ここでユニットテスト

私はコードの重複を削減し、このクラスを拡張する具体的なクラスによって実装されるいくつかのメソッドを強制する抽象クラスを作成しました。

 
abstract class BaseClass 
{ 
    protected $arrayField; 

    ... 

    public function getModifiedArrayField($constraints) 
    { 
     // do things to $arrayField and return a modified 
     // version of the arrayField. Depends only on the 
     // $constraints and some `array_*` functions 
     return $modifiedArray; 
    } 

    // ... some other methods for reducing code duplication 

    // ... abstract methods that needs to be implemented 

} 

抽象クラスそのものの具体的なメソッドをテストすることをお勧めします。

$arrayFieldには、具体的なクラスの抽象メソッドが設定されます。

私はそのプロパティを変更するメソッドの機能をテストしたかったので(突然変異しません)、私は以下のような単体テストを書きました。

 

class BaseClassTest extents PHPUnit_Framework_TestCase 

    private $sut; 

    public function setUp() 
    { 
     $mockObj = $this->getMockFromAbstractClass(BaseClass::class); 
     $ref = new ReflectionClass($mockObj); 
     $ref_prop = $ref->getProperty('arrayField'); 
     $ref_prop->setAccessible(true); 
     $ref_prop->setValue($mockObj, [an_array]); 
     $this->sut = $mockObj; 
    } 

    // .. some test methods that tests methods of abstract class 

    public function testGetModifiedArrayFieldReturnsExpectedArray() 
    { 
     $expected = [array_i_expect]; 
     $actual = $this->sut->getModifiedArrayField([constraints_i_provide]); 

     $this->assertEquals($expected, $actual); 
    } 

今、私はそれだけでテストのために可視性を変更するためにリフレクションを使用することをお勧めではないことをお読みください。

  1. はテストコミュニティは、このアプローチだけで「軽い犯罪」とない大きな犯罪を見つけるん:

    だから私は2つの質問をしましたか?

  2. 私は反射を取り除くことができるようにこのクラスを別に設計する必要がありますか?はいの場合は、提案しているアプローチはありますか?

UPDATE:

Schleisによってanswerは考えて私を得た、インターネット上の友達といくつかのリソースを持ついくつかのチャットの後、私は関数に追加の引数を導入することで、この問題に取り組むことにしました私はテストする必要があった。

私は、関数を一般化して、それをArrayHelperの種類のクラスに移動しようとすることでさらに進めます。これは、1)簡単にテストし、2)必要に応じてコードの他の部分でメソッドを利用できるようにします。

答えて

1

リフレクションの問題は、内部のクラスを公開していることです。単体テストは、コードが正しく動作することを証明するのに役立ちますが、リファクタリングを行い、現在の機能を変更していないことを確認することもできます。

リフレクションを使用して内部プロパティの表示を変更すると、そのプロパティを後で削除/変更できることを意味します。たとえば、あなたはそれを即座に計算することができますか、それと似たようなものがあります。

クラスをテストすることは難しく、コードの匂いです。

なぜ$arrayFieldは抽象メソッドによってのみ設定されますか? getModifiedArrayField()を呼び出す前に、このクラスの実装でそのメソッドを呼び出さないとどうなりますか?

あなたの投稿の名前と説明に基づいて、このクラスとメソッドで意図していることを伝えるのは難しいです。しかし、私はあなたがあなたのクラスがやりたいことが何であるかをもっと考慮する必要があると思います。クラスを変更して、コンストラクタに$arrayFieldを指定するか、このクラスの値を設定する簡単なパブリックメソッドを提供する必要があります。

+0

あなたの答えをありがとう。あなたの質問について:抽象メソッドは、データプロバイダからの 'arrayField'の値を塗りつぶすハイドレーターのようなものです。そして私がテストしたいメソッドは、データを別のフォーマットに変換するだけで、既存のコードベースが返されたデータにそのことを実行できるようにします。私はより良い考えは、別のクラスに変換を移動し、このクラスが何を返すか、それを実行するか、関数への追加の引数を渡すことだと思いますが、パフォーマンスオーバーヘッドについてはあまりよく分かりません。 – cipher

関連する問題