Jeroen De Dauw
Jeroen De Dauw

Reputation: 10908

PHPUnit assert no method is called

I have a ClassA that uses a ServiceB. In a certain case, ClassA should end up not invoking any methods of ServiceB. I now want to test this and verity no methods are indeed called.

This can be done as follows:

$classA->expects( $this->never() )->method( 'first_method' );
$classA->expects( $this->never() )->method( 'second_method' );
...

Is there a way to simply state "no method should be called on this object" rather then having to specify a restriction for each method?

Upvotes: 48

Views: 21665

Answers (3)

Yala Yala Herzlin
Yala Yala Herzlin

Reputation: 622

you could also mock a method and a data provider, and make sure it never is called. without making any assertions, because it is not called, it means it has passed the test.

<?php
    /**
     * @dataProvider dataProvider
     */
    public function checkSomethingIsDisabled( $message, $config, $expected)
    {
        $debugMock = $this->getMockBuilder('APP_Class_Name')
            ->disableOriginalConstructor()
            ->setMethods(array('_helper'))
            ->getMock();

        $debugMock = $this->getPublicClass($debugMock);
        $debugMock->_config = $config;
        $viewContent = new stdClass;
        $debugMock->_functionToTest($viewContent);
    }

    public function dataProvider()
    {
        return [
                'dataset'=>
                    [
                        'message' => 'Debug Disabled',
                        'config' => (object) array(
                            'values' => (object) array(
                                'valueThatWhenFalseDoesntExecuteFunc'=> false
                            )
                        ),
                        // in a probably needed complimentary "imaginary" test we probably  
                        // will have the valueThatWhenFalseDoesntExecuteFunc set to true and on
                        // expected more information to handle and test.
                        'expected' => null
                    ]
                ];
    }

Upvotes: 0

Oleksandr Boiko
Oleksandr Boiko

Reputation: 355

You can use method MockBuilder::disableAutoReturnValueGeneration.

For example, in your test overwrite default TestCase::getMockBuilder:

    /**
     * @param string $className
     * @return MockBuilder
     */
    public function getMockBuilder($className): MockBuilder
    {
        // this is to make sure, that not-mocked method will not be called
        return parent::getMockBuilder($className)
            ->disableAutoReturnValueGeneration();
    }

Advantages:

  • all your mocks won't be expected to call anything than mocked methods. No need to bind ->expects(self::never())->method(self::anything()) to all of them
  • you still can set new mocks. After ->expects(self::never())->method(self::anything()) you can't

Works for PhpUnit v7.5.4 (and probably, later ones).

Upvotes: 3

Cyprian
Cyprian

Reputation: 11374

Yes, it's quite simple, try this:

$classA->expects($this->never())->method($this->anything());

Upvotes: 93

Related Questions