7

被験者の一部:

class AddOptionsProviderArgumentPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        if(!$container->hasDefinition('gremo_highcharts')) {
            return;
        }

        if(!$container->hasParameter('gremo_highcharts.options_provider')) {
            return;
        }

        // ...
    }
}

私はそれを主張したい:

  • hasDefinition()パラメータ「gremo_highcharts」を指定して呼び出すと返されますfalse
  • メソッドprocess()が戻ります。つまり、他のメソッドは呼び出されません

1 つの解決策は、次の への呼び出しについてアサートすることhasParameter()です。

public function testProcessWillReturnIfThereIsNoServiceDefinition()
{
    $container = $this->getMockedContainerBuilder();
    $pass = new AddOptionsProviderArgumentPass();

    $container->expects($this->once())
        ->method('hasDefinition')
        ->with($this->equalTo('gremo_highcharts'))
        ->will($this->returnValue(false));

    // Expects that hasParameter() is never invoked
    $container->expects($this->never())
        ->method('hasParameter');

    $pass->process($container);
}

しかし、それはエレガントなソリューションではないようです。

4

4 に答える 4

3

表現any methodするには、 を使用できます$this->anything()

完全な例:

<?php

class fooTest extends PHPUnit_Framework_TestCase {
    public function testNeverCallNothing() {
        $mock = $this->getMock('mockMe');
        $mock->expects($this->never())->method($this->anything());
        //$mock->bar();
    }
}

class mockMe {
    public function bar() {}
}

出力:

PHPUnit 3.7.10-4-ga0bccf3 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 6.50Mb

OK (1 test, 1 assertion)

メソッド呼び出しでコメントする場合

$mock->bar();

次に出力します。

PHPUnit 3.7.10-4-ga0bccf3 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 6.50Mb

There was 1 failure:

1) fooTest::testNeverCallNothing
mockMe::bar() was not expected to be called.

.../tests/neverCallMe/fooTest.php:9

FAILURES!
Tests: 1, Assertions: 0, Failures: 1.

1 つのメソッド呼び出しのみを許可し、他のメソッドへの呼び出しは許可しない

これは少し醜く見えますが、機能します

<?php

class fooTest extends PHPUnit_Framework_TestCase {

    public function testNeverCallNothing() {
        $mock = $this->getMock('mockMe');
        $mock->expects($this->once())->method('foo');
        $mock->expects($this->never())->method(
            $this->logicalNot($this->matches('foo'))
        );
        $mock->foo();
        //$mock->bar();
    }


}

class mockMe {
    public function bar() {}
    public function foo() {}
}

動作します。他のメソッド呼び出しでコメントすると、上記のように失敗します。

複数のメソッドを呼び出せるようにしたい場合は、もう少し冗長になります。

$this->logicalNot(
    $this->logicalOr(
        $this->matches('foo'),
        $this->matches('baz'),
        $this->matches('buz')
    )
)
于 2012-12-19T21:09:12.713 に答える
2

例外的なケースですか?その場合、最初の戻り値(とにかくvoidを返すのはなぜですか?)を特定の例外をスローするように変更できます。次に、PHPUnitを使用して、特定の例外が実際にキャッチされていることを確認します。

編集:また、Phakeを使用すると、テストの最後に次のようなものを書くことができます:(PHPUnitモックオブジェクトで->never()を呼び出すのと同様)

Phake::verify($container, Phake::times(0))->hasParameter();

これにより、スタブメソッド呼び出しと、メソッド(スタブされているかどうかに関係なく)が呼び出されていることの確認が区別されます。

于 2012-12-19T11:29:48.623 に答える
1

このような方法をテストするときは、全体像を見るようにしてください。ifsとsのレベルに降りないでreturn、より高くしてください。の後に他の呼び出しが行われていないことを主張することによりreturn、実際にテストするのは PHP のネイティブ ステートメントであり、メソッドのロジックではありません。それはあなたがsを信用していないようですreturn。私の言葉を借りて、returnステートメントの後、そのメソッドでは何も実行されません:)

代わりに、あなたのメソッドのロジックをテストしてください!

ロジックは何ですか?

あなたのコードによると、このクラスAddOptionsProviderArgumentPassとそのprocessメソッドがあります。このpocessメソッドは を受け取り、ContainerBuilderそれを何らかの方法で処理します。したがって、テストする必要があるのは、processメソッドが適切に機能することです。メソッドif内の は、 を正常に処理するために満たす必要があるいくつかの制約を表していますContainerBuilder

processが成功したかどうかをどのように理解しますか?

戻り値の型によって。

何も返さない場合はどうなりますか?

その副作用を確認してください。に対して行うことはどれですかContainerBuilder

だから、これが私がそれをどのように見るかです。

/**
 * @test
 */
public function shouldNotProcessWithoutHighcharts()
{
    // Arrange
    $container = $this->buildContainer();
    $container->removeDefinition('gremo_highcharts');
    $pass = new AddOptionsProviderArgumentPass();

    // Act
    $pass->process($container);

    // Assert
    $this->assertFalse($container->hasWhatYouNeedItToHaveAfterProcessing())
}

/**
 * @test
 */
public function shouldNotProcessWithoutHighchartsOptionsProvider()
{
    // Arrange
    $container = $this->buildContainer();
    $container->getParameterBag()->remove('gremo_highcharts.options_provider');
    $pass = new AddOptionsProviderArgumentPass();

    // Act
    $pass->process($container);

    // Assert
    $this->assertFalse($container->hasWhatYouNeedItToHaveAfterProcessing())
}

private function buildContainer()
{
    $container = new ContainerBuilder();
    $container->setParameter('gremo_highcharts.options_provider');
    $container->setDefinition('gremo_highcharts');
    return $container;
}

最後のメモ

sの順序に依存しないでくださいif。変わる可能性があります。

于 2012-12-20T06:34:07.540 に答える