51

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?

3 Answers 3

96

Yes, it's quite simple, try this:

$classA->expects($this->never())->method($this->anything());
Sign up to request clarification or add additional context in comments.

2 Comments

Nowadays you should likely use $classA->expects(self::never())->method(self::anything());
Do you have a source for that @ptkoz ? I'm returning to PHPUnit for the first time in a while, and according to the docs at docs.phpunit.de/en/10.5/assertions.html it still says "The short answer is: there is no right way. And there is no wrong way, either. It is a matter of personal preference."
3

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).

1 Comment

Starting with PHPUnit 10, these base methods have been made final, so you can no longer override getMockBuilder(). Thankfully, starting with v11.1.0, we can add the new #[DisableReturnValueGenerationForTestDoubles] attribute on the test class. docs.phpunit.de/en/11.3/…
0

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
                    ]
                ];
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.