Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Brain Monkey to mock class methods? #54

Closed
Tabrisrp opened this issue Oct 8, 2019 · 4 comments
Closed

How to use Brain Monkey to mock class methods? #54

Tabrisrp opened this issue Oct 8, 2019 · 4 comments
Labels
answered For question with an answer question

Comments

@Tabrisrp
Copy link

Tabrisrp commented Oct 8, 2019

This is more a question on the right use of expect than an issue.

I'm trying to test that a method was called, but I'm not sure I'm doing it right.

I have a dependency class with a purge method

namespace Vendor\Name;

class Dependency {
    public function purge( $url ) {}
}

And another class using this dependency and method in a clean_domain method

namespace Vendor\Name;

class Handler {
    public function __construct( Dependency $dependency ) {
        $this->dependency = $dependency;
    }

    public function clean_domain( $url ) {
        $this->dependency->purge( $url );
    }
}

In my tests I have the following test method

public function testShouldPurge() {
        $dependency = $this->createMock('Vendor\Name\Dependency');

        $handler = new Handler( $dependency );

        Functions\expect( 'Vendor\\Name\\purge' )
            ->times(1)
            ->withAnyArgs();

        $handler->clean_domain( 'http://example.org' );
    }

But am getting the error Mockery\Exception\InvalidCountException: Method Vendor_Name_Purge (<Any Arguments>) from Mockery_0 should be called exactly 1 times but called 0 times. when running the tests.

What am I missing here?

@gmazzap gmazzap self-assigned this Oct 8, 2019
@gmazzap
Copy link
Collaborator

gmazzap commented Oct 8, 2019

Hi @Tabrisrp

Brain Monkey is a tool to mock functions, not class methods.

If you're using modern PHPUnit version, you've at least two options to mock class methods without Brain Monkey.

Built-in PHPUnit mock builder

The first is to make use of built-in PHPUnit mock builder:

public function testShouldPurge() {

    $url = 'http://example.org';

    $dependency = $this->getMockBuilder(\Vendor\Name\Dependency::class)
        ->setMethods(['purge'])
        ->getMock();

    $dependency
        ->expects($this->once())
        ->method('purge')
        ->with($this->equalTo($url));

    $handler = new Handler($dependency);

    $handler->clean_domain($url);
}

The documentation for more advanced usage can be found in PHPUnit docs.

Prophecy

The second option is to use Prophecy, which IIRC is included in PHPUnit since v6:

public function testShouldPurge() {

    $url = 'http://example.org';

    $dependency = $this->prophesize(\Vendor\Name\Dependency::class);
    $dependency->purge($url)->shouldBeCalled();

    $handler = new Handler($dependency->reveal());

    $handler->clean_domain($url);
}

Please refer to Prophecy docs for more advanced usage.

However, if you're using Brain Monkey, you've a 3rd option.

Mockery

Brain Monkey requires Mockery so, having it in you vendor folder, you can use it without much effort.

And if you're following the docs to setup tests for Brain Monkey, your tests are already setup to use it.

So you can also do something like this:

public function testShouldPurge() {

    $url = 'http://example.org';

    $dependency = \Mockery::mock(\Vendor\Name\Dependency::class);
    $dependency->shouldReceive('purge')->once()->with($url);

    $handler = new Handler($dependency);

    $handler->clean_domain($url);
}

As usual, please refer to Mockery docs for more advanced usage.

In test suites that use Brain Monkey, to use Mockery to mock class methods has the benefit to use same API for both class methods and functions (or WP hooks).

In fact, Brain Monkey at its core is a "bridge" between the function-redefinition feature provided by Patchwork and the mock capabilities of Mockery.

@gmazzap
Copy link
Collaborator

gmazzap commented Oct 8, 2019

I'm keeping this issue open, because I often got asked similar questions.

I will change the title for the benefit of people who'll come later.

@gmazzap gmazzap changed the title InvalidCountException when using expect How to use Brain Monkey to mock class methods? Oct 8, 2019
@gmazzap gmazzap added the answered For question with an answer label Oct 8, 2019
@Tabrisrp
Copy link
Author

Tabrisrp commented Oct 8, 2019

Thank you for the fast and detailed answer, using Mockery directly works perfectly in my case 👍

@gmazzap
Copy link
Collaborator

gmazzap commented Dec 12, 2022

Changed my mind about keeping issues open for answered questions. I guess if this is necessary it should be added to documentation.

@gmazzap gmazzap closed this as completed Dec 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
answered For question with an answer question
Projects
None yet
Development

No branches or pull requests

2 participants