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

Feature request: a way to capture arguments #508

Closed
marcaube opened this issue Sep 28, 2015 · 9 comments
Closed

Feature request: a way to capture arguments #508

marcaube opened this issue Sep 28, 2015 · 9 comments
Labels
Feature Request request a new feature

Comments

@marcaube
Copy link

As requested by @davedevelopment on twitter, here's a feature request for a method to capture arguments, just like Phake::capture().

I had a situation recently where this would have been useful. I was writing a class to implement our EventDispatcherInterface using league/event. With this library, listeners can be of type callableor League\Event\ListenerInterface. To make it compatible with our ListenerInterface, our dispatcher wraps the listeners in an anonymous function.

final class LeagueDispatcher implements EventDispatcherInterface
{
    // ...

    public function addListener($eventName, ListenerInterface $listener)
    {
        // wrap the listener in a callable, to make it compatible with League\Event\Emitter
        $leagueListener = function ($event, $payload) use ($listener) {
            return $listener->handle($event->getName(), $payload);
        };

        $this->emitter->addListener($eventName, $leagueListener);
    }
}

In my unit tests, I'd like to make sure this handle() method is called on the listener with the proper arguments. But the only (obvious) way to do it would be to capture the second argument of the addListener expectation.

class LeagueDispatcherTest extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    public function testCanRegisterAnEventListener()
    {
        $emitter = m::mock('League\Event\EmitterInterface');

        // If Mockery could capture the callable argument like Phake can, we could execute it and set
        // expectations on the listener mock to make sure the handle() method is called and get 100% coverage.
        $emitter->shouldReceive('addListener')->once()->with('foo.bar', m::type('callable'));

        $listener = m::mock('Acme\EventDispatcher\ListenerInterface');

        $dispatcher = new \Acme\EventDispatcher\LeagueDispatcher($emitter);

        $dispatcher->addListener('foo.bar', $listener);
    }
}
@davedevelopment
Copy link
Collaborator

@marcaube thank you for adding this!

Just so you know, the way to do it now is to use andReturnUsing or Mockery::on, but neither are as a nice as Phake's option.

I don't use Mockery::on very often, but I believe you use it like this:

$emitter->shouldReceive('addListener')->once()->with('foo.bar', m::on(function ($callable) {
    $callable(new Event(), new Payload()); // I don't know the correct types, but you get the idea
});

That is, on receiving the second argument to "EmitterInterface::addListener", run it through this anonymous function, which in turn just runs the callable that was sent.

@marcaube
Copy link
Author

Thanks for the workaround, I couldn't figure out how to do it on my own.

@aik099
Copy link

aik099 commented Sep 28, 2015

Wow. I never knew, that m::on even exists. It allows to define a matcher in real time or just transforms incoming argument without any kind of validation?

@davedevelopment
Copy link
Collaborator

@aik099 it's there for complicated matchers I believe

@robertbasic robertbasic added the Feature Request request a new feature label May 5, 2017
@robertbasic
Copy link
Collaborator

For what it's worth, Mockery::on has a cookbook entry: http://docs.mockery.io/en/latest/cookbook/mockery_on.html

@robertbasic
Copy link
Collaborator

@marcaube is the \Mockery::on sufficient for what you initially wanted to do? Just trying to see if we need some additional functionality here or we got it covered with on? Thanks!

@marcaube
Copy link
Author

@robertbasic I think on did the trick at the time, but it's been > 2 years and 2 jobs ago 😉

@robertbasic
Copy link
Collaborator

@marcaube fair enough, thanks for taking the time to reply! :)

Given that the feature is in there, I'm going to close this issue. If someone still wants to see this done/improved in Mockery, feel free to reopen the ticket. You'll get bonus karma if you provide a pull request as well :)

@jasonmccreary
Copy link
Contributor

Took a stab at making this a bit more expressive with Mockery::capture() in #1020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request request a new feature
Projects
None yet
Development

No branches or pull requests

5 participants