bici
bici

Reputation: 47

MockBuilder doesn't see method in Interface

I'm trying to mock Throwable interface but MockBuilder doesn't see getPrevious() method.

    $throwableMock = $this->getMockBuilder(\Throwable::class)
        ->disableOriginalConstructor()
        ->getMock();

    $throwableMock->method('getPrevious')
        ->willReturn($domainExceptionMock);

I get this error:

Trying to configure method "getPrevious" which cannot be configured because it does not exist, has not been specified, is final, or is static

If i add addMethods to mock builder, like this:

$throwableMock = $this->getMockBuilder(\Throwable::class)
        ->addMethods(['getPrevious'])
        ->disableOriginalConstructor()
        ->getMock();

I get the following error:

Trying to set mock method "getPrevious" with addMethods(), but it exists in class "Throwable". Use onlyMethods() for methods that exist in the class

What am i doing wrong?

Upvotes: 0

Views: 943

Answers (2)

Turbo
Turbo

Reputation: 688

Throwable::getPrevious() is either final or static so you cannot mock that.

If you create a class with final method and try to mock it you will get the same error message.

class Foo {
  final public function say()
  {

  }
}

$throwableMock = $this->getMockBuilder(Foo::class)
                              ->getMock();

$throwableMock->method('say')
              ->willReturn('xxx');

// Trying to configure method "say" which cannot be configured because it does not exist, has not been specified, is final, or is static

So you should mock the concrete Exception class instead.

Upvotes: 1

Alister Bulman
Alister Bulman

Reputation: 35139

I'm not sure what you're trying to do with the mocked exception, but you may find it easier to build a real object, and then throw that:

class SanityTest extends TestCase
{
    public function testThrowingMock(): void
    {
        $domainExceptionMock = new \RuntimeException('hello');
        $exception = new \Exception('msg', 0, $domainExceptionMock);

        $tst = $this->createMock(Hello::class);  // class Hello {public function hello() {} }
        $tst->method('hello')
            ->willThrowException($exception);

        try {
            $tst->hello();
        } catch (\Exception $e) {
            $this->assertInstanceOf(\RuntimeException::class, $e->getPrevious());
        }
    }
}

Mocking everything can be more difficult than setting up & using, and/or checking the real objects after the fact.

Upvotes: 0

Related Questions