Unit testing triggered events

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Unit testing triggered events

Julian Vidal
I'm trying to make sure that my events are indeed getting fired and I came
up with this unit test. The test works but asserting that true equals true
seems like a hack. Is there a proper way to test this?

$eventManager->attach('mymethod.post', function() {
    $this->assertTrue(true);
});

Julian.
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Artur Bodera
On Thu, Oct 3, 2013 at 5:48 PM, Julian Vidal <[hidden email]> wrote:

> $eventManager->attach('mymethod.post', function() {
>     $this->assertTrue(true);
> });
>

This is wrong, because if it doesn't get fired, the test will also pass.

You can do something like this:

$wasFired = false;
$eventManager->attach('mymethod.post', function() use (&$wasFired) {
    $wasFired = true;
});
$this->assertTrue($wasFired);



--
[hidden email]
+48 695 600 936
http://thinkscape.pro
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Marco Pivetta
Also wrong =D

@julian use a real mock!

$em = $this->getMock('Zend\\EventManager\\EventManagerInterface');
$em->expects($this->once())->method('trigger')->with(...);

That should be the proper way :)
On 5 Oct 2013 18:39, "Artur Bodera" <[hidden email]> wrote:

> On Thu, Oct 3, 2013 at 5:48 PM, Julian Vidal <[hidden email]>
> wrote:
>
> > $eventManager->attach('mymethod.post', function() {
> >     $this->assertTrue(true);
> > });
> >
>
> This is wrong, because if it doesn't get fired, the test will also pass.
>
> You can do something like this:
>
> $wasFired = false;
> $eventManager->attach('mymethod.post', function() use (&$wasFired) {
>     $wasFired = true;
> });
> $this->assertTrue($wasFired);
>
>
>
> --
> [hidden email]
> +48 695 600 936
> http://thinkscape.pro
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Norbert Máté
Marco, could you please finish the example. In the with you give the
parameters for the trigger method and that's all?

This way you just trigger an event. Am I wrong?
How do you know if the event was caught?

Thanks,
Norbert.


On 5 October 2013 20:08, Marco Pivetta <[hidden email]> wrote:

> Also wrong =D
>
> @julian use a real mock!
>
> $em = $this->getMock('Zend\\EventManager\\EventManagerInterface');
> $em->expects($this->once())->method('trigger')->with(...);
>
> That should be the proper way :)
> On 5 Oct 2013 18:39, "Artur Bodera" <[hidden email]> wrote:
>
> > On Thu, Oct 3, 2013 at 5:48 PM, Julian Vidal <[hidden email]>
> > wrote:
> >
> > > $eventManager->attach('mymethod.post', function() {
> > >     $this->assertTrue(true);
> > > });
> > >
> >
> > This is wrong, because if it doesn't get fired, the test will also pass.
> >
> > You can do something like this:
> >
> > $wasFired = false;
> > $eventManager->attach('mymethod.post', function() use (&$wasFired) {
> >     $wasFired = true;
> > });
> > $this->assertTrue($wasFired);
> >
> >
> >
> > --
> > [hidden email]
> > +48 695 600 936
> > http://thinkscape.pro
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Marco Pivetta
You don't. It's a unit test. You don't care about what happens outside your
unit. You just trust what your code executes, and verify that an event is
triggered.

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/


On 22 October 2013 16:44, Norbert Máté <[hidden email]> wrote:

> Marco, could you please finish the example. In the with you give the
> parameters for the trigger method and that's all?
>
> This way you just trigger an event. Am I wrong?
> How do you know if the event was caught?
>
> Thanks,
> Norbert.
>
>
> On 5 October 2013 20:08, Marco Pivetta <[hidden email]> wrote:
>
>> Also wrong =D
>>
>> @julian use a real mock!
>>
>> $em = $this->getMock('Zend\\EventManager\\EventManagerInterface');
>> $em->expects($this->once())->method('trigger')->with(...);
>>
>> That should be the proper way :)
>> On 5 Oct 2013 18:39, "Artur Bodera" <[hidden email]> wrote:
>>
>> > On Thu, Oct 3, 2013 at 5:48 PM, Julian Vidal <[hidden email]>
>> > wrote:
>> >
>> > > $eventManager->attach('mymethod.post', function() {
>> > >     $this->assertTrue(true);
>> > > });
>> > >
>> >
>> > This is wrong, because if it doesn't get fired, the test will also pass.
>> >
>> > You can do something like this:
>> >
>> > $wasFired = false;
>> > $eventManager->attach('mymethod.post', function() use (&$wasFired) {
>> >     $wasFired = true;
>> > });
>> > $this->assertTrue($wasFired);
>> >
>> >
>> >
>> > --
>> > [hidden email]
>> > +48 695 600 936
>> > http://thinkscape.pro
>> >
>>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Artur Bodera
In reply to this post by Marco Pivetta
On Sat, Oct 5, 2013 at 7:08 PM, Marco Pivetta <[hidden email]> wrote:

> Also wrong =D
>
>
Julian: If you just care if any event is fired at all, use the Mock that
Marco suggested.
Minimal, theoretical example would be something like this:

    $em = $this->getMock('Zend\\EventManager\\EventManagerInterface');
    $em->expects($this->atLeastOnce())->method('trigger'));
    $someComponentUsingEm->setEventManager($em);

This test above will fail unless something has been triggered at least once.

If you want to test if specific event has been triggered, then you'd need
to use a closure as I've previously suggested. That is because ::trigger()
method can be called in 4 different
styles<https://github.com/zendframework/zf2/blob/master/library/Zend/EventManager/EventManagerInterface.php#L20-L37>,
and PHPUnit does not support this kind of argument resolution. Inside a
closure you can introspect the event object and check its properties.

Alternatively, you can also use self-shunting
subclass<http://phpunit.de/manual/3.0/en/mock-objects.html>
.


--
[hidden email]
+48 695 600 936
http://thinkscape.pro
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Artur Bodera
On Tue, Oct 22, 2013 at 8:06 PM, Artur Bodera <[hidden email]> wrote:

> If you want to test if specific event has been triggered, then you'd need
> to use a closure as I've previously suggested. That is because ::trigger()
> method can be called in 4 different styles<https://github.com/zendframework/zf2/blob/master/library/Zend/EventManager/EventManagerInterface.php#L20-L37>
> ,


Clarification: unless of course you know _exactly_ how your component is
calling trigger() method on EM. In such case you can use ->with()
tests of PHPUnit
stubs<http://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs>
.


--
[hidden email]
+48 695 600 936
http://thinkscape.pro
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Julian Vidal
Artur,

> Julian: If you just care if any event is fired at all, use the Mock that
Marco suggested.

You mean Norbert :)


On Tue, Oct 22, 2013 at 2:08 PM, Artur Bodera <[hidden email]> wrote:

>
> On Tue, Oct 22, 2013 at 8:06 PM, Artur Bodera <[hidden email]> wrote:
>
>> If you want to test if specific event has been triggered, then you'd need
>> to use a closure as I've previously suggested. That is because ::trigger()
>> method can be called in 4 different styles<https://github.com/zendframework/zf2/blob/master/library/Zend/EventManager/EventManagerInterface.php#L20-L37>
>> ,
>
>
> Clarification: unless of course you know _exactly_ how your component is
> calling trigger() method on EM. In such case you can use ->with() tests of PHPUnit
> stubs<http://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs>
> .
>
>
>
> --
> [hidden email]
> +48 695 600 936
> http://thinkscape.pro
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Norbert Máté
Ok. I wanted to test a logger module. In the Module.php I have set up a
shared event listener and I wanted to test that if I somewhere will trigger
a 'log' event this module will catch it. Maybe it is silliness to test this?


On 22 October 2013 21:18, Julian Vidal <[hidden email]> wrote:

> Artur,
>
> > Julian: If you just care if any event is fired at all, use the Mock that
> Marco suggested.
>
> You mean Norbert :)
>
>
> On Tue, Oct 22, 2013 at 2:08 PM, Artur Bodera <[hidden email]> wrote:
>
> >
> > On Tue, Oct 22, 2013 at 8:06 PM, Artur Bodera <[hidden email]> wrote:
> >
> >> If you want to test if specific event has been triggered, then you'd
> need
> >> to use a closure as I've previously suggested. That is because
> ::trigger()
> >> method can be called in 4 different styles<
> https://github.com/zendframework/zf2/blob/master/library/Zend/EventManager/EventManagerInterface.php#L20-L37
> >
> >> ,
> >
> >
> > Clarification: unless of course you know _exactly_ how your component is
> > calling trigger() method on EM. In such case you can use ->with() tests
> of PHPUnit
> > stubs<
> http://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs>
> > .
> >
> >
> >
> > --
> > [hidden email]
> > +48 695 600 936
> > http://thinkscape.pro
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Marco Pivetta
You'd simply verify that the listener aggregate is attached correctly:

$evm = $this->getMock('Zend\EventManager\EventManagerInterface');

$evm->expects($this->once())->method('attach')->with($this->isCallback());

$listener = new YourListener();

$listener->attach($evm);

And then that callbacks work:

$listener = new YourListener();

$listener->attach($evm);

$bar = $listener->someCallbackMethod($event); // $event should be an event
interface instance
// assert stuff here



Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/


On 22 October 2013 20:34, Norbert Máté <[hidden email]> wrote:

> Ok. I wanted to test a logger module. In the Module.php I have set up a
> shared event listener and I wanted to test that if I somewhere will trigger
> a 'log' event this module will catch it. Maybe it is silliness to test
> this?
>
>
> On 22 October 2013 21:18, Julian Vidal <[hidden email]> wrote:
>
> > Artur,
> >
> > > Julian: If you just care if any event is fired at all, use the Mock
> that
> > Marco suggested.
> >
> > You mean Norbert :)
> >
> >
> > On Tue, Oct 22, 2013 at 2:08 PM, Artur Bodera <[hidden email]> wrote:
> >
> > >
> > > On Tue, Oct 22, 2013 at 8:06 PM, Artur Bodera <[hidden email]>
> wrote:
> > >
> > >> If you want to test if specific event has been triggered, then you'd
> > need
> > >> to use a closure as I've previously suggested. That is because
> > ::trigger()
> > >> method can be called in 4 different styles<
> >
> https://github.com/zendframework/zf2/blob/master/library/Zend/EventManager/EventManagerInterface.php#L20-L37
> > >
> > >> ,
> > >
> > >
> > > Clarification: unless of course you know _exactly_ how your component
> is
> > > calling trigger() method on EM. In such case you can use ->with() tests
> > of PHPUnit
> > > stubs<
> > http://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs
> >
> > > .
> > >
> > >
> > >
> > > --
> > > [hidden email]
> > > +48 695 600 936
> > > http://thinkscape.pro
> > >
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Stefano Torresi
CONTENTS DELETED
The author has deleted this message.
Reply | Threaded
Open this post in threaded view
|

Re: Unit testing triggered events

Norbert Máté
Thanks for the answers.

Regards,
Norbert.


On 23 October 2013 13:26, Stefano Torresi <[hidden email]> wrote:

> As Marco wrote, you generally don't want to test event listeners
> within your Module, because that would need much more mocking.
>
> To make listener testing easier, you want to have them in concrete
> instances of AbstractListenerAggregate or implementations of
> ListenerAggregateInterface using ListenerAggregateTrait, so you can
> actually test them as individual units.
>
> I can link an example of a listener class [1] and its unit test [2],
> but please bear in mind that much of that code is largely inspired by
> the work of other members of the zf2 community, so all credit goes to
> them. That means you can find much better examples elsewhere on
> Github. (i.e. Doctrine modules testing suites are the ones I've read,
> I suggest you check them out [3][4]).
>
> If you then want to go further, you can functionally test the whole
> Module class to make sure it has a legit configuration, registers all
> the services needed and attaches the listener to the EventManager
> during the MVC bootstrap event. That involves building an actual
> ServiceManager instance with a test application configuration and
> manually triggering the module loading via the actual ModuleManager
> service. Nevertheless, this should come after you have a pretty much
> complete unit test suite, since it would involve a lot of dependencies
> that are assumed to be already tested, so they are given to actually
> work.
>
> Cheers.
>
> Stefano Torresi
>
> [1]
> https://github.com/stefanotorresi/MyI18n/blob/feature/MyBackend-support/src/MyI18n/Listener/MissingTranslation.php
> [2]
> https://github.com/stefanotorresi/MyI18n/blob/feature/MyBackend-support/tests/MyI18nTest/Listener/MissingTranslationTest.php
> [3] https://github.com/doctrine/DoctrineModule/tree/master/tests
> [4] https://github.com/doctrine/DoctrineORMModule/tree/master/tests
>