27

メソッドを呼び出してその応答をアサートするかなり標準的な単体テストを作成しようとしていますが、テストしているメソッドは同じクラス内の別のメソッドを呼び出しており、少し手間がかかります。

その1つのメソッドをモックしたいのですが、テスト中のメソッドをそのまま実行し、他のメソッドの呼び出しから返されたモック値のみを使用します。

できるだけ単純にするために、例を簡略化しました。

class MyClass
{

    // I want to test this method, but mock the handleValue method to always return a set value.

    public function testMethod($arg)
    {

        $value = $arg->getValue();

        $this->handleValue($value);

    }


    // This method needs to be mocked to always return a set value.

    public function handleValue($value)
    {

        // Do a bunch of stuff...
        $value += 20;

        return $value;

    }

}

テストを書く私の試み。

class MyClassTest extends \PHPUnit_Framework_TestCase
{


    public function testTheTestMethod()
    {

        // mock the object that is passed in as an arg
        $arg = $this->getMockBuilder('SomeEntity')->getMock();
        $arg->expects($this->any())
            ->method('getValue')
            ->will($this->returnValue(10));

        // test handle document()
        $myClass = new MyClass();

        $result = $myClass->testMethod($arg);

        // assert result is the correct
        $this->assertEquals($result, 50);

    }

}

MyClass オブジェクトをモックしようとしましたが、それを行って testMethod を呼び出すと、常に null が返されます。1 つのメソッドをモックする方法が必要ですが、残りのオブジェクトはそのままにしておきます。

4

2 に答える 2

28

テストしているクラスをモックし、モックするメソッドを指定できます。

$mock = $this->getMockBuilder('MyClass')
    ->setMethods(array('handleValue'))
    ->getMock();

$mock->expects($this->once())
    ->method('handleValue')
    ->will($this->returnValue(23)) //Whatever value you want to return

ただし、IMO これはテストに最適なアイデアではありません。 このようなテストは、リファクタリングをより困難にします。クラスが持つはずの動作ではなく、クラスの実装を指定しています。テストを困難にする多くの複雑な作業を行っている場合handleValueは、ロジックを別のクラスに移動し、それをクラスに注入することを検討してください。次に、そのクラスのモックを作成して に渡すことができますtestMethod。そうすることで、その動作を適応させる必要がMyClassある場合に、より拡張可能handleValue

http://www.oodesign.com/strategy-pattern.html

原則として、テストしているシステムをモックするべきではありません。

于 2013-08-16T19:39:34.217 に答える